Java/PHP/C ... 幾種語言 RSA 的互操作
阿新 • • 發佈:2019-01-10
最近有一個專案,涉及到和別的網站合作,雙方通訊的鑑權計劃是通過 RSA 來做。由於可能涉及到不同的開發環境,於是要研究一下各個語言對 RSA 的支援
openssl 預設創建出來的公金鑰檔案是 PEM 格式的,但 Java API 匯入密碼只能是 DER 格式,特別是金鑰必須用 PKCS#8 編碼。這就需要對 openssl 產生出來的檔案做一下轉換
-
- openssl rsa -inform PEM -in rsapriv.pem -outform DER -pubout -out rsapub.der
- openssl pkcs8 -topk8 -inform PEM -in rsapriv.pem -outform DER -nocrypt -out rsapriv.der
- 基礎演算法的標準是 openssl 的:RSA_private_encrypt/RSA_public_decrypt、RSA_public_encrypt/RSA_private_decrypt 這4個函式,因為 PHP 的 openssl 模組也只提供了這 4 個基礎函式(不要幻想用非 openssl 模組之外的東西來做 RSA 運算,比如 PEAR 的 Crypt_RSA,速度慢到令人髮指)
- 要注意上述 4 個函式裡,可使用的 padding 引數只有那麼有限的幾種。對應 Java 裡面 Cipher.getInstance() 的引數,只能用 "RSA/NONE/PKCS1Padding" 或 "RSA/NONE/NoPadding"(或許 "RSA/None/OAEPPadding" 是對應RSA_PKCS1_OAEP_PADDING,但我沒有深究了)。預設 PHP 裡的 padding 是 RSA_PKCS1_PADDING
- 關於 python... 嗯,直接用 ctypes 就好啦
- 用 RSA 簽名都是首先將文字做一個單向 hash,然後用私鑰將簽名加密;校驗端拿到簽名和文字,用公鑰將簽名解密,對比是否是文字的 hash。openssl 因此封裝了 RSA_sign/RSA_verify 來做這個事情。
- 但 openssl 的幾個 NID 雜湊演算法和標準的sha1/md5好像不太一樣,PHP 幾乎無法和這兩個函式互操作。
- Java API 中 Signature.getInstance() 倒是可以用 "MD2withRSA"、"MD5withRSA" 或 "SHA1withRSA",但也不清楚是否可以和 openssl 的 NID_md2/NID_md2WithRSAEncryption、NID_md5/ NID_md5WithRSAEncryption/NID_md5WithRSA、NID_sha1/NID_sha1WithRSAEncryption/NID_sha1WithRSA 對應起來,仍然需要花時間校驗。
總之為了更多語言的互操作能力,我們現在沒有用 RSA_sign/RSA_verify 這兩個封裝好的函式。