net,ios中rsa加解密使用的是pkcs1,而java使用的是pkcs8
如果是按1024取模(通常都是1024),pkcs1格式的私鑰長度應該是812。如果是pkcs8的格式的密鑰長度為861。
下載安裝openssl:https://pan.baidu.com/s/1ggQJIIR
我這邊使用的是Win64OpenSSL_Light-1_1_0g.exe
PKCS1私鑰生成:
OpenSSL> genrsa -out pkcs1_private.pem 1024 Generating RSA private key, 1024 bit long modulus .........++++++ .............................++++++ e is 65537 (0x10001)
內容:
-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCYMTaH4NMw5fQsgx3pv8xaAxhOdtUz/m5nfl9XHtGboXNzUzx/ ehh8c3RgpGcig83JXOYOXafmx3OS28Ed3e2fmC5Yo5RD6DRHnBCid28EjQ5PgCTd dNqDvcXU3YMH4sO1qNBx5MQpk92Kt/NdquIJmzhgpjP15MO5CFHcU90ZvQIDAQAB AoGANlvdjkrPI/f+bqemV4caBkx0shHftOJ7rJuGkid/1oakJdzlDuMdO9ZBCwOt krZhGjsEML1i6xryPNIg9/n8lSdQqIUW61HXYwKUK5xQWz/MstWbbIx3t5driQFR Fv53NLdemeF/0AJiD5COO1fkoM+1By2LlI0ths8cQLcOpgECQQDIc46yV1N5IuS0 MYD0LgggaJ08WF0PrwjXgs+DRp3+ZE5WTs1JDkBQM9E598xbmy7AAFtdtR3L5CH8 5Qh+KfwJAkEAwl4MuRMdIjiHiw1YoIUliy6t3XPvxeOEiG/P15adKrxI5A5QylM0 TtbZT3YZurdy3nrJ75LxuU9cSYKzxtVFFQJAMboJElD7kjeHyPPm66xns7KAHzJE k9l2NhBrbkOcejlj/aE65/6zEbJpGxpQBgGvTU5JXCvMIoKLs/MVckb0EQJASze+ ULkW4zFhMuy9SZF9T/mGi1bciYZcubgbhODifbFTu/3WQhYk/gWjH18i4eEwcOyv zSjepsoRetk73UyXaQJAOfr3Gg1dGvoLiwZ3fXoDVupahnKg73SAd72+24qQs2AT 16T8FKop259xisLu+WSUTfSUhao5qOpZJ/PTwFRlzw== -----END RSA PRIVATE KEY-----
PKCS1私鑰轉換為PKCS8(該格式一般Java調用)
OpenSSL> pkcs8 -topk8 -inform PEM -in pkcs1_private.pem -outform pem -nocrypt -out pkcs8_private.pem
內容:
-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJgxNofg0zDl9CyD Hem/zFoDGE521TP+bmd+X1ce0Zuhc3NTPH96GHxzdGCkZyKDzclc5g5dp+bHc5Lb wR3d7Z+YLlijlEPoNEecEKJ3bwSNDk+AJN102oO9xdTdgwfiw7Wo0HHkxCmT3Yq3 812q4gmbOGCmM/Xkw7kIUdxT3Rm9AgMBAAECgYA2W92OSs8j9/5up6ZXhxoGTHSy Ed+04nusm4aSJ3/WhqQl3OUO4x071kELA62StmEaOwQwvWLrGvI80iD3+fyVJ1Co hRbrUddjApQrnFBbP8yy1ZtsjHe3l2uJAVEW/nc0t16Z4X/QAmIPkI47V+Sgz7UH LYuUjS2GzxxAtw6mAQJBAMhzjrJXU3ki5LQxgPQuCCBonTxYXQ+vCNeCz4NGnf5k TlZOzUkOQFAz0Tn3zFubLsAAW121HcvkIfzlCH4p/AkCQQDCXgy5Ex0iOIeLDVig hSWLLq3dc+/F44SIb8/Xlp0qvEjkDlDKUzRO1tlPdhm6t3LeesnvkvG5T1xJgrPG 1UUVAkAxugkSUPuSN4fI8+brrGezsoAfMkST2XY2EGtuQ5x6OWP9oTrn/rMRsmkb GlAGAa9NTklcK8wigouz8xVyRvQRAkBLN75QuRbjMWEy7L1JkX1P+YaLVtyJhly5 uBuE4OJ9sVO7/dZCFiT+BaMfXyLh4TBw7K/NKN6myhF62TvdTJdpAkA5+vcaDV0a +guLBnd9egNW6lqGcqDvdIB3vb7bipCzYBPXpPwUqinbn3GKwu75ZJRN9JSFqjmo 6lkn89PAVGXP -----END PRIVATE KEY-----
生成公鑰:
PKCS1的私鑰生成公鑰:
OpenSSL> rsa -in pkcs1_private.pem -pubout -out pkcs1_public.pem
writing RSA key
內容:
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYMTaH4NMw5fQsgx3pv8xaAxhO dtUz/m5nfl9XHtGboXNzUzx/ehh8c3RgpGcig83JXOYOXafmx3OS28Ed3e2fmC5Y o5RD6DRHnBCid28EjQ5PgCTddNqDvcXU3YMH4sO1qNBx5MQpk92Kt/NdquIJmzhg pjP15MO5CFHcU90ZvQIDAQAB -----END PUBLIC KEY-----
PKCS8的私鑰生成公鑰:
OpenSSL> rsa -in pkcs8_private.pem -pubout -out pkcs8_public.pem
writing RSA key
內容:
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYMTaH4NMw5fQsgx3pv8xaAxhO dtUz/m5nfl9XHtGboXNzUzx/ehh8c3RgpGcig83JXOYOXafmx3OS28Ed3e2fmC5Y o5RD6DRHnBCid28EjQ5PgCTddNqDvcXU3YMH4sO1qNBx5MQpk92Kt/NdquIJmzhg pjP15MO5CFHcU90ZvQIDAQAB -----END PUBLIC KEY-----
結果發現兩個公鑰都是一樣的。
下面鏈接里面有在線生產地址:http://tool.chacuo.net/cryptrsapkcs1pkcs8
上面的轉換都沒有私鑰密碼
注意:
使用rsa進行加密的時候,如果報不正常長度,那么就要進行分段加解密。
RSA加解密: 1024位的證書,加密時最大支持117個字節,解密時為128; 2048位的證書,加密時最大支持245個字節,解密時為256。 加密時支持的最大字節數:證書位數/8 -11(比如:2048位的證書,支持的最大加密字節數:2048/8 - 11 = 245) .NET中的RSA加密算法為了提高安全性,在待加密數據前要添加一些隨機數,因此,使用.NET中的RSA加密算法一次最多加密117字節數據(多於117字節需要拆分成多段分別加密再連接起來),經過加密后得到一個長度為128字節的加密數據。 RSA實際可加密的明文長度最大也是1024bits,但問題就來了:如果小於這個長度怎么辦?就需要進行padding,因為如果沒有padding,用戶無法區分解密后內容的真實長度,字符串之類的內容問題還不大,以0作為結束符,
但對二進制數據就很難理解,因為不確定后面的0是內容還是內容結束符。只要用到padding,那么就要占用實際的明文長度,於是才有117字節的說法。
我們一般使用的padding標准有NoPPadding、OAEPPadding、PKCS1Padding等,其中PKCS#1建議的padding就占用了11個字節。
如果大於這個長度怎么辦?很多算法的padding往往是在后邊的,但PKCS的padding則是在前面的,此為有意設計,有意的把第一個字節置0以確保m的值小於n。
這樣,128字節(1024bits)-減去11字節正好是117字節,但對於RSA加密來講,padding也是參與加密的,所以,依然按照1024bits去理解,但實際的明文只有117字節了。
在對接中使用流程:
一共有兩組四個密鑰:A的公鑰(PUB_A),A的私鑰(PRI_A);B的公鑰(PUB_B),B的私鑰(PRI_B)。 公鑰一般用來加密,私鑰用來簽名。 通常公鑰是公開出去的,但是私鑰只能自己私密持有。 公鑰和私鑰唯一對應,用某個公鑰簽名過得內容只能用對應的私鑰才能解簽驗證;同樣用某個私鑰加密的內容只能用對應的公鑰才能解密。 這時A向B發送信息的整個簽名和加密的過程如下: 1、A先用自己的私鑰(PRI_A)對信息(一般是信息的摘要)進行簽名。 2、A接着使用B的公鑰(PUB_B)對信息內容和簽名信息進行加密。 這樣當B接收到A的信息后,獲取信息內容的步驟如下: 1、用自己的私鑰(PRI_B)解密A用B的公鑰(PUB_B)加密的內容; 2、得到解密后的明文后用A的公鑰(PUB_A)解簽A用A自己的私鑰(PRI_A)的簽名。 從而整個過程就保證了開始說的端到端的唯一確認。A的簽名只有A的公鑰才能解簽,這樣B就能確認這個信息是A發來的;A的加密只有B的私鑰才能解密,這樣A就能確認這份信息只能被B讀取。
但是在我的使用過程中,發現只能公鑰加密,私鑰解密,反之則不可以,私鑰可以用來加簽,對應的公鑰可以用來驗簽。(應該是我哪里沒搞懂,所以在不能私鑰加密,公鑰解密)
現在一般對接就是
1.用對方的私鑰對消息進行加簽生成sign,再將消息message跟sign使用對方的公鑰進行加密
2.對方接收到數據以后,先用自己的私鑰進行解密,再用私鑰對解密出來的message進行加簽,與傳遞過來的sign進行對比
RSA只是一個加密的算法,加簽需要先對內容進行HASH然后再加密,比如SHA1WithRSA就是一個常用的RSA加簽算法。