生活随笔
收集整理的這篇文章主要介紹了
JWT,JWE,JWS和RSA2
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
JWT,以及與JWS和JWE之間的關系
簡而言之,JWT是一種安全規范,主要用于在雙方之間傳遞安全數據。而JWS和JWE是實現安全傳輸的兩種方式,JWS用于對傳輸報文的簽名與驗簽,JWE用于對敏感數據的加密解密。
JWS
官方文檔直通車:JWS文檔
JWS由三部分組成,header,payload和sign
header主要包含alg:標識用的什么算法加密。
crit:包括header里除了文檔里規定字段之外的其他字段。
其他的字段,可視情況而定。
example
{"alg": "RS256","kid": "201909031543","crit": ["UPI-UUID", "UPI-TIMESTAMP", "UPI-APPID", "UPI-REQPATH"],"UPI-UUID": "07d2d-dfaa-412e-88e0-75d038b98237","UPI-TIMESTAMP": "1568263226","UPI-APPID": "M0050001","UPI-REQPATH": "/getInfo"
}
payload,這里可以放非加密數據的報文也可以放官方文檔里要求的字段,我在實際應用中,是將報文經過Base64編碼之后放在payload里,
sign,對(base64enc)header.(base64enc)payload進行簽名,具體用的什么簽名算法,根據header里的alg字段判斷。
Q1:sign通過base64編碼,因為官方文檔,我見有寫需要base64編碼,不然驗簽報錯:
java.security.SignatureException: Signature length not correct: got 344 but was expecting 256
這個問題解決參考博客。概述就是簽名和驗簽的時候用的編碼和解碼方式要一致。
RSA
以下代碼借鑒別人博客,但連接我忘了,
/*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 1024;/*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 1024;/*** 獲取密鑰對** @return 密鑰對*/public static KeyPair getKeyPair() throws Exception {KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");generator.initialize(1024);return generator.generateKeyPair();}/*** 獲取私鑰** @param privateKey 私鑰字符串* @return*/public static PrivateKey getPrivateKey(String privateKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);return keyFactory.generatePrivate(keySpec);}/*** 獲取公鑰** @param publicKey 公鑰字符串* @return*/public static PublicKey getPublicKey(String publicKey) throws Exception {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());X509EncodedKeySpec keySpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(publicKey));return keyFactory.generatePublic(keySpec);}/*** RSA加密** @param data 待加密數據* @param publicKey 公鑰* @return*/public static String encrypt(String data, PublicKey publicKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);int inputLen = data.getBytes().length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offset = 0;byte[] cache;int i = 0;// 對數據分段加密while (inputLen - offset > 0) {if (inputLen - offset > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);}out.write(cache, 0, cache.length);i++;offset = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();// 獲取加密內容使用base64進行編碼,并以UTF-8為標準轉化成字符串// 加密后的字符串return new String(Base64.encodeBase64String(encryptedData));}/*** RSA解密** @param data 待解密數據* @param privateKey 私鑰* @return*/public static String decrypt(String data, PrivateKey privateKey) throws Exception {Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] dataBytes = Base64.decodeBase64(data);int inputLen = dataBytes.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offset = 0;byte[] cache;int i = 0;// 對數據分段解密while (inputLen - offset > 0) {if (inputLen - offset > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(dataBytes, offset, inputLen - offset);}out.write(cache, 0, cache.length);i++;offset = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();// 解密后的內容return new String(decryptedData, "UTF-8");}/*** 簽名** @param data 待簽名數據* @param privateKey 私鑰* @return 簽名*/public static String sign(String data, PrivateKey privateKey) throws Exception {byte[] keyBytes = privateKey.getEncoded();PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey key = keyFactory.generatePrivate(keySpec);Signature signature = Signature.getInstance("SHA256withRSA");signature.initSign(key);signature.update(data.getBytes());return new String(Base64.encodeBase64(signature.sign()));}/*** 驗簽** @param srcData 原始字符串* @param publicKey 公鑰* @param sign 簽名* @return 是否驗簽通過*/public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {byte[] keyBytes = publicKey.getEncoded();X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey key = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance("SHA256withRSA");signature.initVerify(key);signature.update(srcData.getBytes());return signature.verify(Base64.decodeBase64(sign.getBytes()));}public static PublicKey getPublicKey1(String key) throws Exception {X509Certificate cert = null;try {cert = X509Certificate.getInstance(key.getBytes());} catch (Exception e) {e.printStackTrace();}PublicKey publicKey = cert.getPublicKey();return publicKey;}
比較好使。其中getPublicKey1 是另一種將密鑰字符串轉publicKey的方式,不同格式的密鑰字符串規范,轉publicKey類型的時候,是不一樣的,對方開發人員沒有簽名驗簽和加解密的sdk或者demo。讓對方把代碼發過來,我才知道,哪里的問題, 關鍵還是自己知道的少,多讀書多看報多敲代碼少睡覺,頭發一天比一天少。
總結
以上是生活随笔為你收集整理的JWT,JWE,JWS和RSA2的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。