使用RSA非对称加密JWT | 燃情岁月

标签: | 发表时间:2019-08-31 14:26 | 作者:
出处:http://www.marcoder.com

JWT几乎是当前分布式开发中无状态token的最佳选择,被越来越多的开发者接受和使用, JWT是基于加密算法的认证方式,省去了到认证服务器的校验过程,认证效率大大提高。更详细的关于JWT的介绍可以点击 这里查看。

通常大家在使用JWT的时候都是使用 HmacSHA256加密钥的加密方式,这种方式严格依赖密钥,在分布式开发的过程中,通常是由认证服务器生成 JWT,然后再由资源校验 JWT的有效性,那么这时候资源服务器就也需要密钥了,认证服务和资源服务很可能是不同的团队开发和维护,密钥在这个过程中传递,很有可能泄漏。密钥一旦泄漏,对方就可以轻易的模拟一个 JWTtoken出来,获取相关信息。

RSA非对称加密算法就可以很好的解决这个问题,认证服务器使用私钥生成 JWT,资源服务器使用公钥去校验 JWT,认证服务去管理私钥,公钥开放给各个资源服务,这样密钥泄漏的可能性就大大降低了。

首先生成公钥和密钥

  1. 打开终端 Terminal或者 iTerm输入以下命令生成私钥:

           
    1
           
    openssl genrsa -out rsa_private_key.pem 1024
  2. 把RSA私钥转换成PKCS8格式

           
    1
           
    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

    注意把控制台输出的私钥内容替换到私钥文件( rsa_private_key.pem)中去。

  3. 生成公钥

           
    1
           
    openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

我这里生成了一份公钥和私钥,用于测试:
私钥 rsa_private_key.pem:

rsa_private_key.pem
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
     
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANDrROfXcbDeMB40
Aa+X/JkRquSj2hXfeMAbkiArzobMEkqwDbdG76/YtSRx6Nem79yqwhUNqNg+lKfM
RMprERDm/+/eX1Tv3YDFzpXZay0md5hZxUQKNqWDobCd7U8twKRDfIw1BfIBtPid
L3RKmOXlJudoa+KeThIRQlT2DHrFAgMBAAECgYBs1OKEU7sqA9TVJwppyqcPpiB8
Es8c7dkdWj94+tkPZ2dv+N5sR0u9MwrJ/XzqOlBhh6KrDP6UB6Ww87wyJiwwy+11
R6Oz2XxPSGBFimoZPyc+dgPC/z63PPpHStXN9027IcaS47sjvtUp6HoCjLZZNht/
oSGxSLZjLDXPm3JLgQJBAP2MAgP387fF8wa5WHqafaNGKW5KI9srwY7szCbleO0Q
EL5eLmYVGUns5sjRFJSjl242QWvkmNlp52TgIkfj+M0CQQDS8LnGa5zeWSzUiDkP
oiMhaJSVQtlgApfsTAA7Lx+M0TENjJcFGFKhGWDSY8AIE1DzYWIijRbC0vsc+WZZ
zOnZAkEA1dt3/7zudv2iJPPEq3UPr94IKByk7cKUemdFMzGus9YvKULrQ/Nb5zzI
1G12PIFXwwBEYirouclYAYADqjuhqQJAHfgDfNRHKjPjMaLU8IqpkRKJoZcoyQI1
UWYO1lnAksIZxQIHZrro6mhvoBR58OvFoX5hceU3qaBN+vTX/MQnKQJBAKX95ga2
NNWQ5Y1TfMEN3X0Ki+y9H64HODxaIuHW/h0W7kVssHSdNPvlEzR+S5pBaVy/6nDH
CUXtz5Uuq3Wm3CA=
-----END PRIVATE KEY----

公钥 rsa_public_key.pem:

rsa_public_key.pem
     
1
2
3
4
5
6
7
     
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQ60Tn13Gw3jAeNAGvl/yZEark
o9oV33jAG5IgK86GzBJKsA23Ru+v2LUkcejXpu/cqsIVDajYPpSnzETKaxEQ5v/v
3l9U792Axc6V2WstJneYWcVECjalg6Gwne1PLcCkQ3yMNQXyAbT4nS90Spjl5Sbn
aGvink4SEUJU9gx6xQIDAQAB
-----END PUBLIC KEY-----

然后开始生成JWT

Java开发中一般使用 jjwt这个库来操作 JWT,在 build.gradle用添加如下依赖即可:

build.gradle
     
1
2
3
     
dependencies {
compile group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.0'
}

生成

生成 JWT的时候需要把签名算法改在 RS256,这一点很重要,这里就表明要求 JWT使用 RSA算法进行加密:

JwtUtils.java
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
     
public static String buildJwtRS256() throws Exception {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;
// 读取私钥
String key = readResourceKey("rsa_private_key.pem");
// 生成签名密钥
byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
.setIssuer("marco")
.setSubject("token")
.signWith(signatureAlgorithm, privateKey);
// jwt中需要传递的内容
builder.claim("id", 10001);
return builder.compact();
}

生成的 JWT字符串如下:

  eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJtYXJjbyIsInN1YiI6InRva2VuIiwiaWQiOjEwMDAxfQ.KmPbzze6zGq5dXDt_XBmwGDsRljHC1dDda5vDroBaJCMdojKczyCUuBYQ203WY7WvgofFnmDw8t2APncDthdEbOxZ2lLXZeiadY6DnSVzOierTzehXGLq7jjONif5I_1vnyrkL5D6EQ2c7RrQNQZmkYGu_pSTkifC9bHJrlKMTs

解析

使用 RSA公钥解析 JWT代码如下:

JwtUtils.java
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
     
public static Claims parseJwtRS256(String jwt) {
Claims claims = null;
try {
// 读取公钥
String key = readResourceKey("rsa_public_key.pem");
// 生成签名公钥
byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
claims = Jwts.parser()
.setSigningKey(publicKey)
.parseClaimsJws(jwt).getBody();
} catch (Exception e) {
e.printStackTrace();
}
return claims;
}

本篇博文代码地址: https://github.com/MTequila/demos/tree/master/jwt-rsa

相关 [rsa 对称加密 jwt] 推荐:

使用RSA非对称加密JWT | 燃情岁月

- -
JWT几乎是当前分布式开发中无状态token的最佳选择,被越来越多的开发者接受和使用, JWT是基于加密算法的认证方式,省去了到认证服务器的校验过程,认证效率大大提高. 更详细的关于JWT的介绍可以点击 这里查看. 通常大家在使用JWT的时候都是使用 HmacSHA256加密钥的加密方式,这种方式严格依赖密钥,在分布式开发的过程中,通常是由认证服务器生成 JWT,然后再由资源校验 JWT的有效性,那么这时候资源服务器就也需要密钥了,认证服务和资源服务很可能是不同的团队开发和维护,密钥在这个过程中传递,很有可能泄漏.

RSA算法原理(二)

- - 阮一峰的网络日志
上一次,我介绍了一些 数论知识. 有了这些知识,我们就可以看懂 RSA算法. 这是目前地球上最重要的加密算法. 我们通过一个例子,来理解RSA算法. 假设 爱丽丝要与鲍勃进行加密通信,她该怎么生成公钥和私钥呢. 第一步,随机选择两个不相等的质数p和q. (实际应用中,这两个质数越大,就越难破解.

RSA算法原理(一)

- - 阮一峰的网络日志
如果你问我,哪一种 算法最重要. 我可能会回答 "公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解. 你可以想象一下,信用卡交易被破解的后果. 进入正题之前,我先简单介绍一下,什么是"公钥加密算法". 1976年以前,所有的加密方法都是同一种模式:.   (1)甲方选择某一种加密规则,对信息进行加密;.

服务器session和jwt之争

- - zzm
session 和cookie的目的相同,都是为了克服http协议无状态的缺陷,但完成的方法不同. session通过cookie,在客户端保存session id,而将用户的其他会话消息保存在服务端的session对象中,与此相对的,cookie需要将所有信息都保存在客户端. 因此cookie存在着一定 的安全隐患,例如本地cookie中保存的用户名密码被破译,或cookie被其他网站收集(例如:1.

什么是 JWT -- JSON WEB TOKEN - 简书

- -
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(. (RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景. JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密.

RSA的SecureID token数据被偷了?

- ripwu - 张志强的网络日志
博客 » 记事本 » 密码学 ». WSJ报道:RSA承认其数据被偷,4000万SecureID token需要被更新. 中国银行银行密钥用的就是RSA生产,就是下图这玩意儿,手里有这玩意儿的同学们要小心了(当然,如果你的账户里的钱没有6位数以上,也不用太担心,毕竟网银的安全性不全依赖于这个设备):.

RSA Security 被攻破的途徑

- MorrisC - Gea-Suan Lin's BLOG
今年三月的時候,RSA Security 被攻破,攻擊者順利取得 SecurID 的資料,這些資料很有可能降低 SecurID 的安全性. 也因此有了 Lockheed Martin 被攻擊的事情. 在官方的說明「Anatomy of an Attack」中,有提到「2011 Recruitment plan.xls」是使用 Excel 檔案,加上 Adobe Flash vulnerability (CVE-2011-0609) 攻入,而這是個 0-day attack (在當時).

RSA详细披露网络攻击

- dunqiu - Solidot
在伦敦举行的RSA安全会议上,RSA执行总裁Art Coviello谴责某个国家对它发动网络攻击,RSA总裁Tom Heiser和首席技术官Eddie Schwartz则披露了攻击的更多细节. 协调合作的攻击者伪装成熟人对RSA雇员实施了一系列鱼叉式钓鱼攻击,目的是渗透进公司网络. 他们发送了内嵌有恶意Flash文件的Excel电子表格,利用0day漏洞建立一个入侵的据点,随后再进行组合攻击,获得SecurID数据的访问权限.

JAVA实现RSA加密解密

- - CSDN博客推荐文章
提供加密,解密,生成密钥对等方法. RSA加密原理概述   :. RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数. 据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积   .  1.选择两个大素数 p,q ,计算 n=p*q;   .  2.随机选择加密密钥 e ,要求 e 和 (p-1)*(q-1)互质   .

[Web 安全] 如何通过JWT防御CSRF

- - SegmentFault 最新的文章
先解释两个名词,CSRF 和 JWT. CSRF (Cross Site Request Forgery),它讲的是你在一个浏览器中打开了两个标签页,其中一个页面通过窃取另一个页面的 cookie 来发送伪造的请求,因为 cookie 是随着请求自动发送到服务端的. JWT (JSON Web Token),通过某种算法将两个 JSON 对象加密成一个字符串,该字符串能代表唯一用户.