使用RSA公私鑰實(shí)現(xiàn)JWT令牌的簽名和驗簽

使用RSA公私鑰實(shí)現(xiàn)JWT令牌的簽名和驗簽

1、什么是JWT令牌

JWT基本概念可從JWT網(wǎng)站獲取,該網(wǎng)站提供了在線DEBUG的功能,對于初次學(xué)習(xí)JWT的同學(xué)來說非常的友好,同時還將各種語言支持JWT的庫提供了列表查閱,方便大家獲取不同語言的第三方庫進(jìn)行學(xué)習(xí)和開發(fā)。如果你已經(jīng)對JWT非常的熟悉并且有過JWT開發(fā)經(jīng)驗,你還可以閱讀RFC7519 JSON Web Token規(guī)范進(jìn)一步學(xué)習(xí)。

2、什么是RSA

RSA是公開密鑰密碼學(xué)體系中的非對稱加密算法,詳細(xì)信息可以閱讀維基百科RSA或者閱讀更專業(yè)的密碼學(xué)書籍,本文不是講解RSA的文章,所以我們在這里就不過多講解RSA的知識。

3、使用RSA對JWT令牌簽名和驗證

私鑰用于簽名令牌,公鑰用于驗證令牌是否為私鑰所簽名。私鑰由令牌生成者持有,驗證令牌的組件可獲得對應(yīng)的公鑰。

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的構(gòu)造函數(shù)支持配置多種參數(shù),包括keysize、SecureRandom和AlgorithmParameterSpec,可根據(jù)安全要求和實(shí)際需要進(jìn)行配置。

使用代碼生成RSA公私鑰對非常的簡單,但是我們需要能夠?qū)SA公私鑰對存儲并且將公鑰分發(fā)給需要的組件這樣才能實(shí)現(xiàn)RSA的作用。PrivateKeyPublicKey都提供了getEncoded()方法獲取按照格式編碼后的內(nèi)容,將key的內(nèi)容存到文件中。

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公私鑰

生產(chǎn)pem格式私鑰:

openssl genrsa -out private_key.pem 3072

將pem格式私鑰轉(zhuǎn)換為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中生成的公私鑰已經(jīng)存儲到了文件,我們首先需要讀取公私鑰內(nèi)容生成java中的PrivateKey和PublicKey,這樣才能進(jìn)行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();

如果簽名錯誤,程序?qū)伋鯯ignatureException異常。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容