RSA对token加密
1 概念
相关概念:
- 明文:未被加密过的数据
- 密文:明文被某种加密算法加密后,就会变成密文
- 密钥:一种参数,明文转换为密文或将密文转换为明文的算法中输入的参数。密钥分为:对称密钥和非对称密钥,分别用在对称加密和非对称加密中。
1.1 对称加密算法(私钥加密)
所谓对称就是指加密和解密都是使用同一个钥匙(密钥)
例如:
①小明要传递一个信息A给小红:A + B = C(小明通过对信息A进行加密后,得到信息C传给小红)
②小红拿到信息C后,C - B = A(小红拿到数据后,用密钥B进行解密,得到初始信息A)
特点:
算法公开、加密和解密速度快,适合对大数据量进行加密;但是与非对称加密相比,安全性降低
1.2 非对称加密算法
非对称加密也要公钥加密。与对称加密相比,安全性更好。对称加密的通信双方使用相同的秘钥,如果任意一方的密钥被泄露,整个通信就会被破解。
非对称加密使用的是一对密钥,即公钥和私钥,且二者成对出现。私钥被自己保存,不能对外泄露。公钥指的是公共的密钥,任何人都可以获得该密钥。用公钥或私钥中的任何一个进行加密,用另一个进行解密。
过程:
明文 + 加密算法 + 公钥 = 密文; 密文 + 解密算法 + 私钥 = 明文
例子:
- 小明对小红说,我这里有箱子A(对应钥匙A),我把A箱子给你(箱子A没锁),钥匙不给你,你给我发的信息放在箱子A里,锁起来,然后我自己用钥匙A就能打开来看。
- 小红对小明说,我这里有箱子B(对应钥匙B),我把B箱子给你(箱子B没锁),钥匙不给你,你给我发的消息放在箱子B里,锁起来,然后我自己用钥匙B就能打开来看。
1.3 加密算法比较
加密算法分为:对称加密和非对称加密【此外还有一类不需要密钥的散列算法】
常见的对称加密算法:DES、3DES、AES、HS256
常见的非对称加密算法:RSA、DSA
散列算法:SHA-1、MD5
2 实际应用
2.1 典型对称加密算法(以HS256为例)
见文章:
https://blog.csdn.net/weixin_45565886/article/details/126557256?spm=1001.2014.3001.5501
企业中开发代码:
packagecom.zi.api.commons.util;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml.jackson.databind.ObjectMapper;importio.jsonwebtoken.*;importjavax.crypto.spec.SecretKeySpec;importjavax.xml.bind.DatatypeConverter;importjava.security.Key;importjava.util.HashMap;importjava.util.Map;/**
* 生成jwt工具类
*/publicclassJJWTRootUtils{//定义对应的编码算法staticSignatureAlgorithm signatureAlgorithm =SignatureAlgorithm.HS256;//盐值staticString secretKey ="d8de020f63754a9fa746ea74b831afc3";//获取key(指定算法和盐值的key对象)privatestaticKeygenerateKey(){//将盐值转成字节byte[] bytes =DatatypeConverter.parseBase64Binary(secretKey);//根据算法和盐值生成对应的key值Key key =newSecretKeySpec(bytes, signatureAlgorithm.getJcaName());return key;}/**
* 将我们的数据使用JWT的方式变成一个token xxx.yyy.zzz
* @param payLoad 负载(数据信息)
* @return
*/publicstaticStringgeneratorToken(Map<String,String> payLoad){ObjectMapper objectMapper =newObjectMapper();try{//构建jwt生成器JwtBuilder builder =Jwts.builder();//将负载信息设置到jwt生成器中JwtBuilder jwtBuilder = builder.setPayload(objectMapper.writeValueAsString(payLoad));//根据签名算法和key值,生成新的jwtBuilderJwtBuilder jwtBuilder1 = jwtBuilder.signWith(signatureAlgorithm,generateKey());String token = jwtBuilder1.compact();return token;}catch(JsonProcessingException e){
e.printStackTrace();}returnnull;}/**
* 根据指定的token, 返回对应的body信息
* @param token
* @return
*/publicstaticClaimsphaseTokenGetBody(String token){JwtParser jwtParser =Jwts.parser().setSigningKey(generateKey());Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);Claims body = claimsJws.getBody();//主要存放的信息return body;}/**
* 根据指定的token获取签名信息
* @param token
* @return
*/publicstaticStringphaseTokenGetSignature(String token){JwtParser jwtParser =Jwts.parser().setSigningKey(generateKey());Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);String signature = claimsJws.getSignature();return signature;}/**
* 根据指定的token获取头信息
* @param token
* @return
*/publicstaticJwsHeaderphaseTokenGetHeader(String token){//获取解析器JwtParser parser =Jwts.parser();//设置签名key(盐值)
parser = parser.setSigningKey(generateKey());//解析tokenJws<Claims> claimsJws = parser.parseClaimsJws(token);JwsHeader header = claimsJws.getHeader();return header;}publicstaticvoidmain(String[] args){//随机获取盐值// System.out.println(UUID.randomUUID().toString().replaceAll("-", ""));Map<String,String> payLoad =newHashMap<>();
payLoad.put("name","curry");String s =generatorToken(payLoad);//eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiY3VycnkifQ.Sf3GiF3p56nLzoAxEHLXcAckPmmPTtecj1_lGT9oV8sSystem.out.println(s);//调用自定义API获取结果Claims claims =phaseTokenGetBody(s);//{name=curry}System.out.println(claims);}}
2.2 典型非对称加密算法(以RSA为例)
2.2.1 概念介绍
RSA算法
RSA算法 的保密强度随其密钥的长度增加而增强。但是,密钥越长,其加解密所耗用的时间也越长。
- RSA加密算法是目前最右影响力的公钥加密算法,且被普遍认为是最优秀的公钥方案之一。
- RSA是第一个能同时用于加密和数字签名的算法,它能够抵抗到目前为止已知的所有密码攻击,已经被ISO推荐为公钥数据加密标准。
- RSA核心思想:将两个大素数相乘十分容易,但是要想对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
2.2.2 具体实现(企业中工具类编写格式)
2.2.2.1 RSAUtil编写
首先编写RSAUtil工具类,用于生成RSA的公钥私钥
//RSA是一种非对称加密算法【公钥、私钥】publicclassRASUtil{/**
* 生成一对公私钥
*/publicstaticvoidgeneratorKey()throwsNoSuchAlgorithmException{//构建一个生成公私钥 RAS算法生成的对象KeyPairGenerator keyPairGenerator =KeyPairGenerator.getInstance("RSA");//初始化生成器 keySize:512起
keyPairGenerator.initialize(512,newSecureRandom());//密钥对KeyPair keyPair = keyPairGenerator.generateKeyPair();//获取私钥RSAPrivateKey privateKey =(RSAPrivateKey) keyPair.getPrivate();//获取公钥RSAPublicKey publicKey =(RSAPublicKey) keyPair.getPublic();//获取私钥字符串String privateKeyStr =newString(Base64.encodeBase64(privateKey.getEncoded()));String publicKeyStr =newString(Base64.encodeBase64(publicKey.getEncoded()));System.out.println("privateKeyStr:"+ privateKeyStr);System.out.println("publicKeyStr:"+ publicKeyStr);//privateKeyStr:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAhUfkmkFtrOlFiX8FmHiYx9mAPpfTA6oKE6VgFLDNQzYO1YMugA0ACChp6n3hfDWOp3XgWWRVmzU+z30h+01lyQIDAQABAkBtvjvKlDNFnDJou9GUsUBD1qDVaVgT/VAcyyApCUeKnehPLMISa5JBTUpJ03cMPh3hV7q4OJQweM7nuJ+GXcCBAiEAx5xHdUM3XnFZ6aQnAvKzPWqV/eqpDRj9aSFiR/vbJ3kCIQCq7rDN2qs1DUo8XS2WcbBOFLMU+uHDuV8rigFe0yyM0QIgfQ5hCotRDh9P6HwKYONy/kBftlQlE2qboRjkPRsCQ2kCIBUoVlokpux6KKYwImRszhXcGg6Ov0Mqvsz02BaUrP8BAiBrxV/0jPm2pr3GJXW5MHhJ4a2LrkYFfWdHQx+gpSJESg==//publicKeyStr:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIVH5JpBbazpRYl/BZh4mMfZgD6X0wOqChOlYBSwzUM2DtWDLoANAAgoaep94Xw1jqd14FlkVZs1Ps99IftNZckCAwEAAQ==}publicstaticvoidmain(String[] args)throwsNoSuchAlgorithmException{generatorKey();}}
注意:企业中工具类中一般是没有main方法的,此处只是为了方便测试
2.2.2.2 JWTAuth0Util工具类编写【包含对称加密与非对称加密】
一般包含方法:
- String genTokenRAS(Map<String, String> payload):基于RSA加密生成token
- DecodedJWT decodedRSA(String token):基于RSA解密生成DecodedJWT
- String getToken(Map<String, String> payload):获取token
- DecodedJWT decodedJWT(String token):解析token
①非对称加密:根据RSA加密生成token
/**
* 根据RSA算法加密生成token
* @param payload
* @return
*/publicstaticStringgenTokenRAS(Map<String,String> payload){//指定过期时间 【3天】Calendar calendar =Calendar.getInstance();
calendar.add(Calendar.DATE,3);//获取一个构建对象【静态内部类】JWTCreator.Builder builder = JWT.create();//将信息、数据(body)信息放到需要的claim里面
payload.forEach((k, v)-> builder.withClaim(k, v));//通过hutool工具类来创建RSA对象RSA rsa =newRSA(PRIVATE_KEY_STR,null);//获取私钥RSAPrivateKey privateKey =(RSAPrivateKey) rsa.getPrivateKey();String token = builder.withExpiresAt(calendar.getTime()).sign(Algorithm.RSA256(null, privateKey));return token;}
②非对称加密:根据RSA解密token
/**
* 使用RSA的方式来解密
* @param token
* @return
* 根据不同的异常来判断当前token到底是什么情况
*/publicstaticDecodedJWTdecodedRSA(String token){//通过公钥获取我们的RSA的公钥对象RSA rsa =newRSA(null, PUBLIC_KEY_STR);RSAPublicKey publicKey =(RSAPublicKey) rsa.getPublicKey();//jwt的验证对象JWTVerifier jwtVerifier = JWT.require(Algorithm.RSA256(publicKey,null)).build();DecodedJWT decodedJWT = jwtVerifier.verify(token);return decodedJWT;}
③对称加密:HMAC256,定义盐值
privatestaticfinalString SECRET ="H2OJ20FC35APACHE";
④对称加密:HMAC256,加密获取token
/**
* 获取token
* @param payload
* @return
*/publicstaticStringgetToken(Map<String,String> payload){//指定过期时间【3天】Calendar calendar =Calendar.getInstance();
calendar.add(Calendar.DATE,3);//获取一个构建对象【静态内部类】JWTCreator.Builder builder = JWT.create();//将body信息放到我们需要生成的claim里面
payload.forEach((k, v)-> builder.withClaim(k, v));//通过指定签名算法和过期时间生成一个tokenString token = builder.withExpiresAt(calendar.getTime()).sign(Algorithm.HMAC256(SECRET));return token;}
⑤对称加密:HMAC256,解密获取数据
/**
* 解析token
* @param token
* @return
*/publicstaticDecodedJWTdecodedJWT(String token){//构建一个验证jwt token的对象JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();//验证以后获取信息的对象DecodedJWT decodedJWT = jwtVerifier.verify(token);//返回信息对象return decodedJWT;}
2.2.2.3 全部代码
packagecom.zi.api.commons.util;importcn.hutool.crypto.asymmetric.RSA;importcom.auth0.jwt.JWT;importcom.auth0.jwt.JWTCreator;importcom.auth0.jwt.JWTVerifier;importcom.auth0.jwt.algorithms.Algorithm;importcom.auth0.jwt.interfaces.DecodedJWT;importjava.security.interfaces.RSAPrivateKey;importjava.security.interfaces.RSAPublicKey;importjava.util.Calendar;importjava.util.HashMap;importjava.util.Map;/**
* 加密解密token
*/publicclassJWTAuth0Util{privatestaticfinalString SECRET ="H2OJ20FC35APACHE";//私钥和公钥privatestaticfinalString PRIVATE_KEY_STR ="MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAjX+A8rA2a8tJNQ2DK5pnfaXqHyv5iSG2KdWJk3GMkfN0VuEO/JvbM0ljQgi6/qPmgUIFgL65meavzJXDMr8IZQIDAQABAkEAh7JZdWRsLGAd6tT0kGJZEXSF3DMN8eb0jZYNg+sHRgdovJtlHZBTiMbSoQphvsYe8dBHplOjktzTipTe0y/rmQIhAMP13C1UFEPdFv9D6mFg+hehr0Jk+vcxOoGFA1o0vOz/AiEAuNnk/2etuErfNdgN9ujc88TAG2mpzBvyxpIHNQridpsCIC44dYBzjnwbT+tRt5zUZOjiCBae/tsDT4txNkM2oUE9AiBoN4jxKi36KlRAEiiFXXI9CV9Z1S/DALrWkzv2/sUBIwIgXgMe3SW4vML/ieQHIEmk+GhDD/NJad9Hs4HOBkNcA1I=";privatestaticfinalString PUBLIC_KEY_STR ="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI1/gPKwNmvLSTUNgyuaZ32l6h8r+YkhtinViZNxjJHzdFbhDvyb2zNJY0IIuv6j5oFCBYC+uZnmr8yVwzK/CGUCAwEAAQ==";/**
* 根据RSA算法加密生成token【非对称】
* @param payload
* @return
*/publicstaticStringgenTokenRAS(Map<String,String> payload){//指定过期时间 【3天】Calendar calendar =Calendar.getInstance();
calendar.add(Calendar.DATE,3);//获取一个构建对象【静态内部类】JWTCreator.Builder builder = JWT.create();//将信息、数据(body)信息放到需要的claim里面
payload.forEach((k, v)-> builder.withClaim(k, v));//通过hutool工具类来创建RSA对象RSA rsa =newRSA(PRIVATE_KEY_STR,null);//获取私钥RSAPrivateKey privateKey =(RSAPrivateKey) rsa.getPrivateKey();String token = builder.withExpiresAt(calendar.getTime()).sign(Algorithm.RSA256(null, privateKey));return token;}/**
* 使用RSA的方式来解密【非对称】
* @param token
* @return
* 根据不同的异常来判断当前token到底是什么情况【比如被伪造...】
*/publicstaticDecodedJWTdecodedRSA(String token){//通过公钥获取我们的RSA的公钥对象RSA rsa =newRSA(null, PUBLIC_KEY_STR);RSAPublicKey publicKey =(RSAPublicKey) rsa.getPublicKey();//jwt的验证对象JWTVerifier jwtVerifier = JWT.require(Algorithm.RSA256(publicKey,null)).build();DecodedJWT decodedJWT = jwtVerifier.verify(token);return decodedJWT;}/**
* 获取token【对称加密】
* @param payload
* @return
*/publicstaticStringgetToken(Map<String,String> payload){//指定过期时间【3天】Calendar calendar =Calendar.getInstance();
calendar.add(Calendar.DATE,3);//获取一个构建对象【静态内部类】JWTCreator.Builder builder = JWT.create();//将body信息放到我们需要生成的claim里面
payload.forEach((k, v)-> builder.withClaim(k, v));//通过指定签名算法和过期时间生成一个tokenString token = builder.withExpiresAt(calendar.getTime()).sign(Algorithm.HMAC256(SECRET));return token;}/**
* 解析token【对称加密】
* @param token
* @return
*/publicstaticDecodedJWTdecodedJWT(String token){//构建一个验证jwt token的对象JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();//验证以后获取信息的对象DecodedJWT decodedJWT = jwtVerifier.verify(token);//返回信息对象return decodedJWT;}publicstaticvoidmain(String[] args){Map<String,String> map =newHashMap<>();
map.put("helicopter","apache");String rsaCodeStr =genTokenRAS(map);System.out.println("非对称加密后的token:"+ rsaCodeStr);DecodedJWT decodedJWT =decodedRSA(rsaCodeStr);String rsaDecodeStr = decodedJWT.getToken();System.out.println("非对称解密后的token:"+ rsaDecodeStr);String hmacCodeStr =getToken(map);System.out.println("对称加密后的token:"+ hmacCodeStr);DecodedJWT decodedJWT1 =decodedJWT(hmacCodeStr);String hmacDeCodeStr = decodedJWT1.getToken();System.out.println("对称解密后的token:"+ hmacDeCodeStr);}}
版权归原作者 NPE~ 所有, 如有侵权,请联系我们删除。