java 实现PGP生成公私钥对生成,生成jwt的token,以及通过token 验证公钥
·
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> <!-- 包含 PEMParser 和 JcaPEMKeyConverter -->
<version>1.77</version>
</dependency>
更多推荐


所有评论(0)