RSA加密原理使用方式簽名驗證


 

 

RSA加密原理使用方式簽名驗證

加密是網絡傳輸中非常重要的一環,它保證了信息的安全性,讓他人無法通過抓包來獲取通訊的信息也無法通過偽造信息而實現對系統的入侵。其中最為常用的信息傳遞加密方式就是RSA加密。

RSA加密原理

RSA與傳統加密方式不同的是,他是非對稱加密,可以在不直接傳遞密鑰的情況下,完成解密。這能夠確保信息的安全性,避免了直接傳遞密鑰所造成的被破解的風險。
RSA加密方式是:
(1)乙方生成兩把密鑰(公鑰和私鑰)。公鑰是公開的,任何人都可以獲得,私鑰則是保密的。
(2)甲方獲取乙方的公鑰,然后用它對信息加密。
(3)乙方得到加密后的信息,用私鑰解密。
RSA非對稱加密算法的原理請參照下面兩篇文章,本文主要講述RSA加密在java程序中的使用。其概念是利用大整數的質數分解的困難性來保障密鑰不被破解。

RSA算法原理part1
RSA算法原理part2

RSA加密傳輸的實現

在加密前首先要生成秘鑰,秘鑰的生成可以使用java中的security包下的KeyPairGenerator來生成指定位數的秘鑰。生成的秘鑰為byte類型,一般可以用文件保存在使用的時候讀取,但是為了方便寫在程序里也可以用base64編碼成字符串,在使用的時候用base64解碼然后獲得秘鑰的對象。
密鑰生成:

/*創建非對稱加密的公鑰和私鑰示例 將生成的公鑰和私鑰用Base64編碼后打印出來*/ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); //一般加密位數為1024 對安全要求較高的情況下可以使用2048 KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); /*將公鑰base64編碼打印出來*/ System.out.println(Base64.encodeBase64String(publicKey.getEncoded())); /*將私鑰base64編碼打印出來*/ System.out.println(Base64.encodeBase64String(privateKey.getEncoded())); 

加密我們需要先將密鑰字符串base64解碼然后生成密鑰對象然后使用。
在java提供的jdk1.5中已經提供了相關加密工具類Cipher類,使用起來也比較方便
加密:

/*公鑰字符串*/ String pubKey="base64編碼的公鑰"; /*X.509 標准中定義的公鑰編碼標准,使用這個類進行轉換*/ X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey)); //獲得公鑰對象 PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); String msg="需要加密的內容"; /*使用Cipher加密*/ /*定義加密方式*/ Cipher cipher = Cipher.getInstance("RSA"); /*使用公鑰和加密模式初始化*/ cipher.init(Cipher.ENCRYPT_MODE, publicKey); /*獲取加密內容以UTF-8為標准轉化的字節進行加密后再使用base64編碼成字符串*/ /*加密后的字符串*/ String enmsg=Base64.encodeBase64String(cipher.doFinal(plainText.getBytes("UTF-8")));

然后同理反向解密
解密:

String priKey="base64編碼的私鑰"; PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(baiduPriKey)); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); String msg="加密后的內容"; Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); /*解密后的內容*/ String demsg = new String(cipher.doFinal(Base64.decodeBase64(msg)), "UTF-8"); 

以上就是加密解密的過程

RSA簽名的實現

RSA加密生成的公鑰和私鑰實際上是一對互相可以加密解密的鑰匙對,換句話說 你可以用私鑰加密,用公鑰解密。但是由於一些特定的加密工具為了方便加密傳輸位數而指定了公鑰的秘鑰值,私鑰是根據公鑰的值計算得出的,所以一般私鑰比較大且安全性更高,留作自己系統去解密其他系統傳來的數據。
但是我們說道,公鑰是可能給復數個其他系統的,你無法得知是哪個系統給你傳輸的這個數據,所以就有了簽名這一說。現在有甲乙兩個系統,甲系統要給乙系統傳輸數據,甲系統的數據使用自己的私鑰對傳遞的信息進行加密,然后加一個簽名字段放入要傳輸的數據中然后整體數據再使用公鑰進行加密,傳輸給乙系統。乙系統拿到數據后,先使用自己的私鑰解密數據,然后剔除簽名字段,然后解密簽名字段看與剔除簽名字段的數據進行對比,這一步叫做驗簽,如果相等則代表此數據時由甲方傳來且數據沒有被篡改。
java中也提供了相應的簽名方法類Signature可以直接使用,現在假設使用json字符串傳輸做一次簽名驗簽的案例
簽名:

/* 1. 准備發送的數據 為保證順序正確這里使用TreeMap*/ TreeMap<String, String> map = new TreeMap<String, String>(); map.put("msg1", "1324679"); map.put("msg2", "A001"); map.put("msg3", "V1.0"); map.put("msg4", ""); /* 2. 計算驗簽字段, sign字段不參與簽名 map轉String方法可以自定義*/ String line = JSON.toJSONString(map); PrivateKey privateKey="自己的私鑰"; //設置簽名加密方式 Signature signature = Signature.getInstance("RSA"); signature.initSign(privateKey);//設置私鑰 //簽名和加密一樣 要以字節形式 utf-8字符集得到字節 signature.update(line.getBytes("UTF-8")); //得到base64編碼的簽名后的字段 String sign = Base64.encodeBase64String(signature.sign()); //將簽名放入map map.put("sign", sign); //將要傳輸的數據轉成json String request = JSON.toJSONString(map); /*進行傳輸(可進行正常加密)*/ .......

驗簽:

... /*獲得請求過來的request(若加密請解密)並轉換成map*/ TreeMap<String, String> map = JSON.parseObject(request, new TypeReference<TreeMap<String, String>>() {}); String sign = map2.get("sign");//獲得簽名 map2.remove("sign");//剔除簽名 String line = JSON.toJSONString(map);//轉化為字符串 PublicKey publicKey = "對方給的公鑰"; //指定簽名類型 Signature signature = Signature.getInstance("RSA"); signature.initVerify(publicKey);//放入公鑰 signature.update(line .getBytes("UTF-8"));//放入數據 //驗簽結果 boolean isPassed= signature.verify(Base64.decodeBase64(sign)); System.out.println("驗簽結果 : " + isPassed); 

實際使用的優化方法

rsa算法是一種取模計算,當加密位數很大時(比如2048位生成密鑰),實際上消耗的計算量還是很大的,而且由於有簽名的存在,相當於傳了兩份數據過去,一正一反加密驗簽消耗的計算量就非常大了,為了優化加密傳輸及減少系統計算量,我們一般需要采取一些優化方法:
1.采取散列算法簡化簽名
簽名實際上只需要驗證數據是否沒有被篡改/是否是對方系統發來的數據 實際上是沒有必要吧整個數據都進行加密傳輸,可以使用散列算法來進行壓縮驗證,常用的有sha256和md5,然后將計算后的值進行簽名,接收方使用同樣的方法進行壓縮驗簽。
2.生成隨機對稱加密密鑰,使用對稱加密加密數據,然后將密鑰進行RSA加密明文傳輸
第一種優化雖然優化了簽名,減少了數據傳輸和運算,但是數據本體還是很大,使用rsa加密仍然需要消耗大量的計算能力,於是就有了這種加密方式,生成隨機的密鑰對稱加密數據,然后將對稱的密鑰進行rsa加密明文傳輸,對方接受到對稱密鑰的rsa加密后的字符串,再用私鑰解密,得到對稱加密的密鑰對數據進行解密。

最后附上完整的加密案例及整理的加密解密工具類:

rsa+aes加密傳輸工具及案例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM