記https請求時證書、公鑰、私鑰、加密的各種問題

最近在做https雙向認證的時候,遇到了各種證書、公鑰、私鑰、加密算法等問題。要解決這些問題,首先應(yīng)該先明確各自的概念到底是什么。

SSL證書:SSL證書讓網(wǎng)站實現(xiàn)加密傳輸、認證服務(wù)器的身份等等。我的理解:證書是服務(wù)器給客戶端的憑證(不管是權(quán)威機構(gòu)還是自己頒發(fā)的),你客戶端只有信任了這個憑證你才能訪問我的數(shù)據(jù),否則就沒得談啊。證書應(yīng)在你所用的網(wǎng)絡(luò)請求框架中事先信任。證書的標準格式等可參考:http://blog.csdn.net/shangy110/article/details/53262630
客戶端公私鑰:客戶端用自己的私鑰對數(shù)據(jù)進行簽名,證明該數(shù)據(jù)確實是我發(fā)的。公鑰由服務(wù)端保留,如果能正常解密,說明身份沒毛病。
服務(wù)器公私鑰:服務(wù)器的公鑰提供給客戶端,客戶端用該公鑰對數(shù)據(jù)進行加密。發(fā)送的數(shù)據(jù)服務(wù)器如果能用自己的私鑰解密,證明這個過程沒問題,你可以來拿數(shù)據(jù)了。公鑰是公開的,服務(wù)端可以給任意需要與其對接的客戶端;私鑰服務(wù)器自己保留。

至于服務(wù)端是要先認證客戶端的身份還是先解密數(shù)據(jù),我覺得無所謂,反正你兩個都得過才行嘛。接下來看看遇到的坑。

客戶端私鑰進行對數(shù)據(jù)簽名時發(fā)生的錯誤:

Caused by: java.lang.IllegalArgumentException: unknown object in getInstance: com.android.org.bouncycastle.asn1.DEROctetString

有些機器可能會是這樣的錯誤:

Caused by: java.lang.IllegalArgumentException: failed to construct sequence from byte[]: Extra data detected in stream

產(chǎn)生這個原因很大一部分是因為私鑰的格式有問題。
比如你通過InputStream輸入私鑰文件,再轉(zhuǎn)成字符串時,頭部的“-----BEGIN RSA PRIVATE KEY-----”,以及尾部的“-----END RSA PRIVATE KEY-----”是應(yīng)該去掉的。所以InputStream轉(zhuǎn)String的代碼變成了這樣:

   public static String inputSteamToString(InputStream inputStream)
    {
        try
        {
            InputStreamReader inputReader = new InputStreamReader(inputStream);
            BufferedReader bufReader = new BufferedReader(inputReader);
            String line = "";
            String Result = "";
            while ((line = bufReader.readLine()) != null)
            {
                if (line.charAt(0) == '-')
                {
                    continue;
                }
                Result += line;
            }
            return Result;
        } catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }

構(gòu)造KeyFactory時發(fā)生的錯誤:

Caused by: java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag

構(gòu)造KeyFactory時,首先需要傳入“算法(algorithm)”參數(shù),如“RSA”。如果僅傳一個algorithm參數(shù),在Android中很有可能發(fā)生上述錯誤(應(yīng)該是Android環(huán)境和Java環(huán)境不一樣的緣故)。
這時候還應(yīng)該傳入一個“提供者(provider)”參數(shù),傳入"BC",即BouncyCastleProvider
這時,構(gòu)造KeyFactory的代碼變成了這樣:

KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");

你可以通過KeyFactory生成相應(yīng)的公鑰和私鑰。

加密算法和格式:

用公鑰對數(shù)據(jù)進行加密時,需要注意加密的算法和格式。通常有如下格式(后面的數(shù)字為對應(yīng)密鑰的長度):

AES/CBC/NoPadding (128)
AES/CBC/PKCS5Padding (128)
AES/ECB/NoPadding (128)
AES/ECB/PKCS5Padding (128)
DES/CBC/NoPadding (56)
DES/CBC/PKCS5Padding (56)
DES/ECB/NoPadding (56)
DES/ECB/PKCS5Padding (56)
DESede/CBC/NoPadding (168)
DESede/CBC/PKCS5Padding (168)
DESede/ECB/NoPadding (168)
DESede/ECB/PKCS5Padding (168)
RSA/ECB/PKCS1Padding (1024、2048)
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024、2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024、2048)

如果后臺拋“javax.crypto.BadPaddingException: Blocktype”這種異常,很多情況下就是格式不正確引起的。在此之前,要確保公私鑰正確(我當時對數(shù)據(jù)用自己的私鑰進行了簽名,但是忘了給后臺公鑰,后臺一直跟我說報上述錯誤。因為自己本身對這方面也不是很了解,所以就把上述格式全部試了一遍...結(jié)果還是不行,后來才發(fā)現(xiàn)沒給公鑰- -)。
在Android中,如下格式的加密方式通常是能解的(公鑰長度2048,RSA加密)。當然這主要取決于加密方式和密鑰長度:

    public static byte[] encrypt(Key key, byte[] src) throws Exception {
        if (src != null && src.length != 0) {
            Cipher e = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            e.init(Cipher.ENCRYPT_MODE, key);
            return e.doFinal(src);

        } else {
            throw new IllegalArgumentException("報文為空");
        }
    }

如果實在不行,我還谷歌到了這種姿勢:

Cipher e = Cipher.getInstance("RSA/NONE/OAEPWithSHA1AndMGF1Padding");
Cipher e = Cipher.getInstance("RSA/None/PKCS1Padding");

只能死馬當活馬醫(yī)咯,不過對我沒啥用。最好的方式是跟后臺對接好,用什么方式加密,就用什么方式解密。

關(guān)于String和byte:

原始的String類型數(shù)據(jù)在網(wǎng)絡(luò)傳輸過程中被認為是不安全的,通常會將String類型的數(shù)據(jù)轉(zhuǎn)成byte數(shù)組,并對其進行Base64編碼后傳輸。服務(wù)器進行解密時,一般先將收到的數(shù)據(jù)Base64解碼,然后再進行相應(yīng)的解密工作。
先這么多,其他的后續(xù)補,有問題歡迎指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容