关于Android中RSA数字签名的理解及使用
- 關于RSA數字簽名Android
- 什么是RSA
- 我自己的理解
- 客戶端請求服務器的數據
- 服務器響應客戶端的數據
- 思路
- 大概流程
- 注意
- 加密解密工具類的代碼
- 使用樣例
關于RSA數字簽名(Android)
近期項目中考慮到數據比較重要,擔心與服務器交互過程中被篡改,所以引用了數據簽名的技術。
什么是RSA:
RSA是一種非對稱的加密算法,RSA的加密解密中有一對密鑰(公鑰和私鑰),通過公鑰加密的密文只能通過對應的私鑰解密,反之亦然。
我自己的理解:
在數據交互中,必須同時知道密鑰對和被加密的字符串(我們暫時先稱為密簽)的生成規則,才能造出合法的數據。下面假設我們的客戶端代碼被反編譯,獲取到了儲存在我們本地的密鑰對,我們分兩種情況進行分析。
客戶端請求服務器的數據
加密的密鑰得到了,但是沒有我們密簽的生成規則,造不出合法的請求數據。
服務器響應客戶端的數據
通過解密的私鑰解密服務器返回的sign值,獲取到了服務器響應數據的密簽生成規則,但是加密響應數據的加密密鑰是保存在服務器的,相對比較安全,所以也造不出合法的響應數據。
所以在這套加密體系中,請求數據的密簽和響應數據的密簽的生成規則應該是不同的。
思路:
在整個交互中一共有兩對密鑰,一對用于服務器的加密(公鑰A)和客戶端的解密(私鑰A),另一對用于服務器的解密(私鑰B)和客戶端的加密(公鑰B)。在客戶端請求時,將請求數據通過RSA加密后連帶要請求的數據一起發送給服務器,服務器收到請求后,首先通過對應的密鑰對請求中加密的數據進行解密,然后對比解密后的內容與請求的內容是否一致,若一致,則可以判定數據是合法的,反之則是不合法的。服務器在響應客戶端請求時,使用相同的方法。(Ps:請求的數據一般都是鍵值對,我們通過與服務器協商,使用相同的規則對數據進行拼接,組成一個字符串后進行加密)
大概流程:
這里假設我們的拼接規則是:鍵=值&鍵=值&…
Created with Rapha?l 2.1.0 客戶端 客戶端 服務器 服務器 {"name":"張三", "age":"12", "sign":"這里是對數據進行拼接后加密的密文" (這里加密之前應該是:name=張三&age=12)} 服務器收到請求后取出sign的值進行解密, 然后通過拼接字符串的方式將出去sign的其 余參數按照規則拼接,如果拼接出來的值與 sign解密得到的值相同,則可以判斷數據是 來自服務器的。 服務器的響應信息中也使用這樣的加密方式, 客戶端得到信息后,使用相同的方法判斷 數據的合法性。注意:
在加解密過程中,openssl生成的密鑰對無法使用。(有大神發現問題希望指出)這里附上一對可用的鑰匙。
—–BEGIN PUBLIC KEY—–
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBJq3d4HJscWh44l/Vh431rbKZ
XxdR+gRSgvINmCuHTlgasRsvKiPgtBtRsj/mzpowuxCOg67xkBQvIoXVs1wiJNuQ
Zi+mVXUQCJelLn5ykCLvNqkugMO9nNtre/2VezjP81t5FeOlEnQMo3AFLSeZv2cc
I9V0DD0IsnIlRH/L8wIDAQAB
—–END PUBLIC KEY—–
—–BEGIN PRIVATE KEY—–
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMEmrd3gcmxxaHji
X9WHjfWtsplfF1H6BFKC8g2YK4dOWBqxGy8qI+C0G1GyP+bOmjC7EI6DrvGQFC8i
hdWzXCIk25BmL6ZVdRAIl6UufnKQIu82qS6Aw72c22t7/ZV7OM/zW3kV46USdAyj
cAUtJ5m/Zxwj1XQMPQiyciVEf8vzAgMBAAECgYBaJ7G0BNWj5HN9KTzOME2ExSS+
DfKWovptgQ12Zva6W0kofE5R/3troOW3hlnpY7n40PfzbWe0/SlOrvCFRQjVXbbR
9a+eZ0xynSuMg8m57q8qHZ/l5dV8ECWsEUC1eFHepWpMDygFv8qgLIV2C5Ot03HW
yGXLzoPJ+GD9U+yA8QJBAP2vKm6Js9wYvK/vtUpX7jScuHHFSZmimoyAz3sOIWZ2
XBKspc0XDzLlIAd6BbC5i9JfTqTNJE0Om20NsuOqOp0CQQDC6g25Go56AZvsXPBh
1I5L0Lj673sBx9wqvAUS6/MCeJT9jBUq8FRDi4KVlkWBzhDP5K+AKnADm40fAVi2
R9PPAkBl2pOVyBH/16rClOLcE4vfceEYRNb1KXUV3o3vYVAFvJXhJZJ4Ur7Wd2ox
tktcllLOR1fjET529dtvoKVnhSx9AkEAsOr9dcyTEk8vlkVts37Zght8K9j/j8g3
IVr0SA5+zvlgUxu5gvYNphmVd+2kPYQrYmgynGTos32XhFMWkK11pQJAFOMAzgSE
PggBQohD4jg7vOvZzFO8M4VDee7yaC5xFpJlJBtol1twlIbzv1HjAgHDeqXChStf
rLegWG4sbnXTMA==
—–END PRIVATE KEY—–
加密解密工具類的代碼
package com.shsy.test.rsa;import android.util.Base64;import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;/*** Created by Shsy on 15-11-27.*/ public class RsaUtils {/*** 獲取公鑰** @param algorithm* @param bysKey* @return*/private static PublicKey getPublicKeyFromX509(String algorithm,String bysKey) throws NoSuchAlgorithmException, Exception {byte[] decodedKey = Base64.decode(bysKey, Base64.DEFAULT);X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey);KeyFactory keyFactory = KeyFactory.getInstance(algorithm);return keyFactory.generatePublic(x509);}/*** 獲取私鑰** @param key* @return* @throws Exception*/public static PrivateKey getPrivateKey(String key) throws Exception {byte[] keyBytes;keyBytes = Base64.decode(key, Base64.DEFAULT);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(keySpec);return privateKey;}/*** 使用公鑰加密** @param content* @param publicKey* @return*/public static String encryptByPublic(String content, String publicKey) {try {PublicKey pubkey = getPublicKeyFromX509("RSA", publicKey);Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");cipher.init(Cipher.ENCRYPT_MODE, pubkey);byte plaintext[] = content.getBytes("UTF-8");byte[] output = cipher.doFinal(plaintext);String s = new String(Base64.encode(output, Base64.DEFAULT));return s;} catch (Exception e) {return null;}}/*** 通過私鑰解密** @param content* @param privateKey* @return*/public static String decryptByPrivate(String content, String privateKey) {try {PrivateKey prikey = getPrivateKey(privateKey);Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");cipher.init(Cipher.DECRYPT_MODE, prikey);byte[] enBytes = Base64.decode(content, Base64.DEFAULT);byte[] deBytes = cipher.doFinal(enBytes);return new String(deBytes);} catch (Exception e) {return null;}} }使用樣例
/**將上面的密鑰復制到對應的""中*/ /**注意:密鑰不包含被"-----BEGIN PUBLIC KEY-----"這樣的頭尾信息*/ /**加密的公鑰*/ pivate final String public_Key=""; /**解密的私鑰*/ pivate final String private_Key=""; /**要加密的內容*/ String s = "Test"; /**加密*/ String ss = RsaUtils.encryptByPublic(s,public_Key); /**解密*/ String sss = RsaUtils.decryptByPrivate(ss,private_Key);總結
以上是生活随笔為你收集整理的关于Android中RSA数字签名的理解及使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中pass关键字
- 下一篇: 【2022持续更新】大数据最全知识点整理