java 实现PGP生成公私钥对生成,以及通过token 验证公钥

1.PgpUtils 生成PGP生成公私钥对 和调用获取token 和验证token

package com.example.schedulelockscreen.util;

import com.example.schedulelockscreen.aes.JwtValidator;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class PgpUtils {

    static {
        // 添加BouncyCastle安全提供者
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    // 生成RSA密钥对(2048位)
    public static KeyPair generateRsaKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
        keyPairGenerator.initialize(2048);
        return keyPairGenerator.generateKeyPair();
    }

    // 生成PGP格式的密钥对字符串数组 [0]=私钥 [1]=公钥
    public static String[] generatePgpKeys(KeyPair keyPair, String identity, char[] passPhrase) throws Exception {
        // 创建PGP密钥对
        JcaPGPKeyPair jcaPGPKeyPair = new JcaPGPKeyPair(
                PGPPublicKey.RSA_GENERAL,
                keyPair,
                new Date()
        );

        // 设置密钥过期时间(秒)
//        PGPSignatureSubpacketGenerator signHashGen = new PGPSignatureSubpacketGenerator();
//        long expirationSeconds = TimeUnit.MINUTES.toSeconds(1);
//        signHashGen.setKeyExpirationTime(true, expirationSeconds);
//

        // 构建密钥加密器
        PGPSecretKey secretKey = new PGPSecretKey(
                PGPSignature.DEFAULT_CERTIFICATION,
                jcaPGPKeyPair,
                identity,
                new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1),
                null,
                null,
                new JcaPGPContentSignerBuilder(jcaPGPKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1),
                new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.CAST5)
                        .setProvider("BC")
                        .build(passPhrase)
        );

        // 生成ASCII格式的密钥字符串
        String privateKeyStr = armorToString(secretKey.getEncoded());
        String publicKeyStr = armorToString(secretKey.getPublicKey().getEncoded());

        return new String[]{privateKeyStr, publicKeyStr};
    }

    // 将字节数组转换为ASCII装甲字符串
    private static String armorToString(byte[] data) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (ArmoredOutputStream armored = new ArmoredOutputStream(out)) {
            armored.write(data);
        }
        return out.toString();
    }

    public static void main(String[] args) throws Exception {
        // 1. 生成密钥对
        KeyPair keyPair = generateRsaKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        // 2. 生成PGP格式密钥
        String identity = "zhangSan@11.com"; // 用户标识
        char[] passPhrase = "123456".toCharArray(); // 私钥保护密码

        String[] pgpKeys = generatePgpKeys(keyPair, identity, passPhrase);
        System.out.println("PGP Private Key:\n" + pgpKeys[0]);
        System.out.println("\nPGP Public Key:\n" + pgpKeys[1]);

        // 3. 生成Token(使用原始私钥)
        String token = TokenUtils.genToken(privateKey);
        System.out.println("\nToken: " + token);

        // 4. 验证Token(使用原始公钥)
        try {
            boolean b = JwtValidator.validateToken(token, publicKey);
            if (b) {
                System.out.println("Token验证成功!");
            } else {
                System.out.println("Token验证失败!");
            }
        } catch (Exception e) {
            System.out.println("Token验证失败: " + e.getMessage());
        }
    }
}

2.TokenUtils 获取token

package com.example.schedulelockscreen.util;


import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.springframework.stereotype.Component;

import java.io.FileReader;
import java.security.PrivateKey;
import java.util.Date;
import java.util.UUID;

/**
 * @author 43616037
 *
 */
@Component
public class TokenUtils {
    public static void main(String[] args) {
        String keyFilePath = "";
        //System.out.println(genToken(keyFilePath));
    }
    public static String genToken(PrivateKey key ) {
        try {
          //  PrivateKey key = readRSAPrivateKey(keyFilePath);

            JwtBuilder jwtBuilder = Jwts.builder().header()
                    .add(Constants.VER, "1.0")
                    .add(Constants.KID, "GRANT_KEY_ID")
                    .add(Constants.TYP, "JWT")
                    .add(Constants.ALG, "RS384").and();

            jwtBuilder = jwtBuilder
                    .audience().single("BCS")
                    .subject("GRANT_PROFILE_ID")
                    .claim(Constants.PAYLOAD_HASH_ALG, "RSASHA256")
                    .claim(Constants.PAYLOAD_HASH, UUID.randomUUID().toString())
                    .issuedAt(new Date())
                    .id(UUID.randomUUID().toString());

            return jwtBuilder.signWith(key, Jwts.SIG.RS384).compact();
        } catch (Exception e) {
            System.out.println("error: " + e);
        }
        return null;
    }

    public static PrivateKey readRSAPrivateKey(String pem) throws Exception {
        try (PEMParser pemParser = new PEMParser(new FileReader(pem))) {
            Object object = pemParser.readObject();
            PrivateKeyInfo keyInfo;
            if (object instanceof PrivateKeyInfo) {
                keyInfo = (PrivateKeyInfo) object;
            } else if (object instanceof org.bouncycastle.openssl.PEMKeyPair) {
                keyInfo = ((org.bouncycastle.openssl.PEMKeyPair) object).getPrivateKeyInfo();
            } else {
                throw new IllegalArgumentException("Unsupported PEM format");
            }
            return new JcaPEMKeyConverter().getPrivateKey(keyInfo);
        }
    }

    public static class Constants {
        /** Constants for request & response. */
        public static final String VER = "ver";
        public static final String TYP = "typ";
        public static final String ALG = "alg";
        public static final String KID = "kid";
        public static final String PAYLOAD_HASH = "payload_hash";
        public static final String PAYLOAD_HASH_ALG = "payload_hash_alg";
    }
}

3.JwtValidator 校验token

package com.example.schedulelockscreen.aes;

import io.jsonwebtoken.*;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileReader;
import java.security.PublicKey;
import java.util.Date;

public class JwtValidator {
    private static final Logger logger = LoggerFactory.getLogger(JwtValidator.class);

    public static PublicKey readPublicKey(String publicKeyPath) throws Exception {
        try (PEMParser pemParser = new PEMParser(new FileReader(publicKeyPath))) {
            Object obj = pemParser.readObject();
            if (obj instanceof SubjectPublicKeyInfo) {
                return new JcaPEMKeyConverter().getPublicKey((SubjectPublicKeyInfo) obj);
            }
            throw new IllegalArgumentException("Unsupported PEM type: " + obj.getClass());
        }
    }

    public static boolean validateToken(String token, PublicKey publicKey) {
        try {
            Jws<Claims> claimsJws = Jwts.parser()
                    .verifyWith(publicKey)
                    .clockSkewSeconds(60) // 时间容差
                    .build()
                    .parseClaimsJws(token);

            // 从 Header 获取 kid
            String kid = claimsJws.getHeader().getKeyId();
            if (!"GRANT_KEY_ID".equals(kid)) {
                return false;
            }
              //校验token 过期时间
//            Claims claims = claimsJws.getBody();
//            if (claims.getExpiration().before(new Date())) {
//                return false;
//            }
            return true;
        } catch (ExpiredJwtException e) {
            logger.error("Token 已过期");
            return false;
        } catch (JwtException e) {
            logger.error("JWT 解析失败: {}", e.getMessage());
            return false;
        }
    }
}

4. maven 依赖

  <!-- JJWT 核心库(需包含 jjwt-api、jjwt-impl、jjwt-jackson) -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.13.0</version> <!-- 2025-11 发布 [citation:2] -->
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.13.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.13.0</version>
            <scope>runtime</scope>
        </dependency>

        <!-- Bouncy Castle 提供 PEM 格式支持 -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk18on</artifactId>
            <version>1.77</version> <!-- 2025 最新版 [citation:6][citation:8] -->
        </dependency>
        <!-- JJWT 核心库(版本需 ≥ 0.12.0-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.12.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.12.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId> <!-- 或 jjwt-gson -->
            <version>0.12.5</version>
            <scope>runtime</scope>
        </dependency>

        <!-- BouncyCastle 密钥处理 -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk18on</artifactId> <!-- 包含 PEMParserJcaPEMKeyConverter -->
            <version>1.77</version>
        </dependency>
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐