美文网首页
使用RSA公私钥实现JWT令牌的签名和验签

使用RSA公私钥实现JWT令牌的签名和验签

作者: 大哥你先走 | 来源:发表于2022-08-01 16:38 被阅读0次

使用RSA公私钥实现JWT令牌的签名和验签

1、什么是JWT令牌

JWT基本概念可从JWT网站获取,该网站提供了在线DEBUG的功能,对于初次学习JWT的同学来说非常的友好,同时还将各种语言支持JWT的库提供了列表查阅,方便大家获取不同语言的第三方库进行学习和开发。如果你已经对JWT非常的熟悉并且有过JWT开发经验,你还可以阅读RFC7519 JSON Web Token规范进一步学习。

2、什么是RSA

RSA是公开密钥密码学体系中的非对称加密算法,详细信息可以阅读维基百科RSA或者阅读更专业的密码学书籍,本文不是讲解RSA的文章,所以我们在这里就不过多讲解RSA的知识。

3、使用RSA对JWT令牌签名和验证

私钥用于签名令牌,公钥用于验证令牌是否为私钥所签名。私钥由令牌生成者持有,验证令牌的组件可获得对应的公钥。

3.1 公私钥生成和存储

在这里我们讲解两种生成公私钥的方法:使用Java中的KeyPairGenerator生成,使用openssl命令

3.1.1 使用KeyPairGenerator生成公私钥

KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair keyPair = generator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();

其中KeyPairGenerator的构造函数支持配置多种参数,包括keysize、SecureRandom和AlgorithmParameterSpec,可根据安全要求和实际需要进行配置。

使用代码生成RSA公私钥对非常的简单,但是我们需要能够将RSA公私钥对存储并且将公钥分发给需要的组件这样才能实现RSA的作用。PrivateKeyPublicKey都提供了getEncoded()方法获取按照格式编码后的内容,将key的内容存到文件中。

String path = "private_key.der";
Files.write(new File(path).toPath(), keyPair.getPrivate().getEncoded());

String publicPath = "public_key2.der";
Files.write(new File(publicPath).toPath(), keyPair.getPublic().getEncoded());

3.1.2 使用openssl命令生成RSA公私钥

生产pem格式私钥:

openssl genrsa -out private_key.pem 3072

将pem格式私钥转换为der格式

openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt

生成公钥

openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der

3.2 读取RSA公私钥

3.1中生成的公私钥已经存储到了文件,我们首先需要读取公私钥内容生成java中的PrivateKey和PublicKey,这样才能进行JWT令牌的签名和验签。

3.2.1 读取私钥:

私钥的编码格式为:PKCS#8

private static PrivateKey getPrivateKey() {
    String privateKeyName = "private_key2.der";
    try {
        byte[] content = Files.readAllBytes(new File(privateKeyName).toPath());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(content);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

3.2.2 读取公钥

公钥的编码格式为:X.509

private static PublicKey getPublicKey() {
    String publicKeyName = "public_key2.der";
    try {
        byte[] keyBytes = Files.readAllBytes(new File(publicKeyName).toPath());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

3.3 生成JWT令牌

本文使用jjwt开源组件来生成JWT令牌

PrivateKey privateKey = getPrivateKey();
Map<String, String> claims = new HashMap<>();
claims.put("user", "chen tong");
String token = Jwts.builder()
    .setClaims(claims)
    .signWith(privateKey)
    .compact();

3.4 验签JWT令牌

PublicKey publicKey = getPublicKey();
Claims claims1 = Jwts.parserBuilder()
    .setSigningKey(publicKey)
    .build().parseClaimsJws(token).getBody();

如果签名错误,程序将会抛出SignatureException异常。

相关文章

网友评论

      本文标题:使用RSA公私钥实现JWT令牌的签名和验签

      本文链接:https://www.haomeiwen.com/subject/mourwrtx.html