RSA在Android、vc、java下加解密實現互通。


最近公司項目需求要對上傳/下載的數據進行AES+RSA的加解密需求,客戶有vc的RSA加解密接口,而且說要與他們的系統兼容,也就是說vc下要用他們的模塊實現加解密。期間過程有幾個坑,原因都是自己的對這些加密的協議/准則/規范不熟,以此文記錄備案。

 

坑1:

首先先是百度java的RSAUtils,網上很多現成的,例如這個:http://www.2cto.com/kf/201408/328112.html,公鑰使用X509的解析類,私鑰使用PKCS#8的解析類。編寫測試程序一切正常。。。

然后就是調試客戶提供的vc模塊,測試程序如下圖

然后走到RSA_EnCrypt的時候就出現錯誤,缺出現了0xC0000005未知性錯誤。(絕對不是輸出沒分配內存or內存不足-_-!!)這下就有點難搞了,打電話咨詢對方,對方就說要遵循openssl標准生成的key哦~然后我汗顏了回他說,我是用你demo生成的key放進去接口用得,還會報錯?然后對方也鄙視我了一下說,你發你的測試程序來看看。

發過去半個小時后,對方就返回一個截圖給我

然后還說:上面的截圖的做法沒錯,只是如果你傳密匙或私匙字符串參數的時候,需要保持格式分割,如在VC里面你可以在每行后面加個\n,如果讀入整個文本即保持了每行后面有\r\n就可以了,這個是標准pem格式的要求,事實上如果直接用openssl命令行生成密匙對並保存為文本,它也是用\n來分割的,直接文本打開是看不到回車換行的。

嗯,以上這句話就是坑1結論,上面說的:用傳統的記事本打開用openssl生成的pem確實沒了\n的格式,就一行串的寫過去,而且可能是java的工具類內部已經處理這種一行串字符串格式的key,實際應用硬編碼或者測試的時候會對我這種小白造成第一印象錯誤,而openssl的接口需要保持這種文本格式才能解析成功。還有,那個begin和end也是需要寫進去的!!!
 
 
坑2
好了,既然java有工具類了,vc有接口了,那就是實現互相加解密吧~先是vc用public加密,java用privatekey解密,恩恩。
然而實踐中中是有各種不知為何,而知后也不過如此的錯誤。首先聲明一點就是,加密后的內容全球99.99%的人都是用base64將其編碼,解密前需先將其這串內容用base64解碼還原,嗯嗯。使用客戶方提供的demo生成的公私密鑰對,vc加密后把加密內容的傳給java平台,然后java使用privatekey解密,遺憾的是java解碼失敗,出錯的原因居然是privatekey解析不成功,這下又摸不着頭腦了,不是說都按openssl的標准嗎?sun公司不會另起標准的吧?
混亂了一陣子,仔細查看log是pkcs8的編碼出錯了,然后又百度pkcs8為何物,直叫我生死相許~.~
http://bbs.csdn.net/topics/190044123  <--- 這鏈接就詳細說明了這些密鑰的分類划分,然后看見到pkcs系列的介紹,然后還有http://blog.csdn.net/jdsjlzx/article/details/41441147這兄弟說的:密鑰就基本生成,不過這樣密鑰對的私鑰是無法在代碼中直接使用的,要想使用它需要借助RSAPrivateKeyStructure這個類,java是不自帶的。所以為了方便使用,我們需要對私鑰進行 PKCS#8編碼!!!
 
然后一個猜測出現在我的腦海里,我的夢里,我的心里,我的記錄里。。。難不成vc的不是按照pkcs#8的?打電話給客戶方,得到答復是:不是pkcs#8,但不記得是pkcs#12還是什么的。=_=
好吧,再看看pkcs#12是何方神聖,鏈接我就不附帶了。蛋疼的是,pkcs#12是證書的協議而且帶密碼的啊,你就一個密鑰字符串,這是哪跟哪呢?
 
再一次在混亂的思維中冷靜下來,客戶方一直說遵從openssl標准,vc的openssl我不是沒用過,最原始的java不能使用的pem文件是什么格式?經百度是pkcs#1,嗯哼!?這里有玄機,立刻再搜索有沒工具把pkcs#1的變pkcs#8的,http://tool.chacuo.net/cryptrsapkcs1pkcs8 <-這網址就是把pkcs#1的私鑰轉成pkcs#8的格式,好吧,再次利用vc的demo生成公私密鑰對(假設是pkcs#1),然后提取私鑰利用工具生成一串pkcs#8格式的密鑰。放進去java測試,解密成功!
 
總結下坑2:java現有的工具都是x509-pkcs#8的公私密鑰對,而vc利用openssl的就很原始很開放的,就怪雙方沒有溝通好,造成坑2一系列的麻煩。
 
 
 
 
坑3,android的rsa隱坑=_=
按道理,java的系統jar包能在android上找到,那為啥java平台的rsa加解密能與vc互通,android就失敗?android加密的內容送到java/vc里解密是一段空串?還有一點奇怪的是,java/vc的rsa加密后的內容都是隨機不一樣的,為啥android的加密后的內容那串字符串居然是一樣的呢?搜索如下文章http://blog.csdn.net/yanzi1225627/article/details/26508035 和 http://blog.csdn.net/anod/article/details/8734608最后就是這個http://my.oschina.net/cwalet/blog/35867,還有這個http://juliusdavies.ca/commons-ssl/pkcs8.html( <-需要翻牆) 慢慢的理解到android的虛擬機與windows上的虛擬機還真不一樣。
 
android自帶的只包含一個 默認的 RSA的最標准算法 是沒填充“RSA/ECB/NoPadding”
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
所以android的每次運行都一樣
然后這個Cipher里提供了第二個參數給你更換算法提供者
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",new org.bouncycastle.jce.provider.BouncyCastleProvider());
這個就是按PKCS1填充的然后每次都不一樣。這就是區別。

坑3結論:無話可說。從得到需求和客戶方溝通到三平台互通用時4天。


免責聲明!

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



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