關於AES演算法 JAVA同C++互解
阿新 • • 發佈:2019-02-09
關於加解密JAVA一般使用的JCE,關於C++可以實現AES加解密的開源專案就多的數不勝數的。
理論上上演算法一樣,對稱金鑰一樣就能夠互相識別了。
相信很多人開始想法都同我一樣,起初我JAVA用JCE,C++使用openssl。
結果發現加密出的密文完全不相同。
JCE中AES支援五中模式:CBC,CFB,ECB,OFB,PCBC;
支援三種填充:NoPadding,PKCS5Padding,ISO10126Padding。
不支援SSL3Padding。不支援“NONE”模式。 好原來有模式和填充一說。
在OPENSSL中直接有一個CBC加解密函式。
填充沒找到,試過後發現C++加密出的內容比JAVA的要長出一截,前面的內容是完全一樣的。
這應該就出現在填充上。本來以為找到問題關鍵就應該很容易解決的。
結果發現OPENSSL的填充是固定實現的,而我所需要解密的java端程式碼不能改動。
一條路走不通咱就換條路。最後發現有一個開源專案Botan什麼都有而且同JCE十分相似並且滿足我要求垮平臺。
附:
假如原始資料長度等於16*n,則使用NoPadding時加密後資料長度等於16*n,其它情況下加密資料長度等於16*(n+1)。
在不足16的整數倍的情況下:
假如原始資料長度等於16*n+m[其中m小於16],除了NoPadding填充之外的任何方式,加密資料長度都等於16*(n+1);
NoPadding填充情況下,CBC、ECB和PCBC三種模式是不支援的,CFB、OFB兩種模式下則加密資料長度等於原始資料長度。
還有一種方案:
在java端採用AES/CBC/PKCS5Padding方式加密的時候,c端要對應的採用CBC模式和PKCS5Padding的填充方式。
我的問題主要就是處在PKCS5Padding的填充方法上面,正確的填充方法應該是:
1.如果明文剛好是16的倍數,則需要在末尾填充長度為16的串,且每個位元組的值為OX16。
2.如果明文不是16的倍數,則需要填充為16的倍數。比如abcd123456長度為10,則需要填充6個位元組,且每個位元組的值為0x06.
填充完成後再進行cbc模式的加密,這樣跟java互相相容就沒有問題了。
只需要用cbc加密模式,填充方式用我上面描述的方法,是沒有問題的。
原始碼沒什麼意義,只是在呼叫openssl的加密函式do_AES_cbc_encrypt前,將源資料串進行了填充。
理論上上演算法一樣,對稱金鑰一樣就能夠互相識別了。
相信很多人開始想法都同我一樣,起初我JAVA用JCE,C++使用openssl。
結果發現加密出的密文完全不相同。
JCE中AES支援五中模式:CBC,CFB,ECB,OFB,PCBC;
支援三種填充:NoPadding,PKCS5Padding,ISO10126Padding。
不支援SSL3Padding。不支援“NONE”模式。 好原來有模式和填充一說。
在OPENSSL中直接有一個CBC加解密函式。
填充沒找到,試過後發現C++加密出的內容比JAVA的要長出一截,前面的內容是完全一樣的。
這應該就出現在填充上。本來以為找到問題關鍵就應該很容易解決的。
結果發現OPENSSL的填充是固定實現的,而我所需要解密的java端程式碼不能改動。
一條路走不通咱就換條路。最後發現有一個開源專案Botan什麼都有而且同JCE十分相似並且滿足我要求垮平臺。
附:
在原始資料長度為16的整數倍時:演算法/模式/填充 16位元組加密後資料長度 不滿16位元組加密後長度 AES/CBC/NoPadding 16 不支援 AES/CBC/PKCS5Padding 32 16 AES/CBC/ISO10126Padding 32 16 AES/CFB/NoPadding 16 原始資料長度 AES/CFB/PKCS5Padding 32 16 AES/CFB/ISO10126Padding 32 16 AES/ECB/NoPadding 16 不支援 AES/ECB/PKCS5Padding 32 16 AES/ECB/ISO10126Padding 32 16 AES/OFB/NoPadding 16 原始資料長度 AES/OFB/PKCS5Padding 32 16 AES/OFB/ISO10126Padding 32 16 AES/PCBC/NoPadding 16 不支援 AES/PCBC/PKCS5Padding 32 16 AES/PCBC/ISO10126Padding 32 16
假如原始資料長度等於16*n,則使用NoPadding時加密後資料長度等於16*n,其它情況下加密資料長度等於16*(n+1)。
在不足16的整數倍的情況下:
假如原始資料長度等於16*n+m[其中m小於16],除了NoPadding填充之外的任何方式,加密資料長度都等於16*(n+1);
NoPadding填充情況下,CBC、ECB和PCBC三種模式是不支援的,CFB、OFB兩種模式下則加密資料長度等於原始資料長度。
還有一種方案:
在java端採用AES/CBC/PKCS5Padding方式加密的時候,c端要對應的採用CBC模式和PKCS5Padding的填充方式。
我的問題主要就是處在PKCS5Padding的填充方法上面,正確的填充方法應該是:
1.如果明文剛好是16的倍數,則需要在末尾填充長度為16的串,且每個位元組的值為OX16。
2.如果明文不是16的倍數,則需要填充為16的倍數。比如abcd123456長度為10,則需要填充6個位元組,且每個位元組的值為0x06.
填充完成後再進行cbc模式的加密,這樣跟java互相相容就沒有問題了。
只需要用cbc加密模式,填充方式用我上面描述的方法,是沒有問題的。
原始碼沒什麼意義,只是在呼叫openssl的加密函式do_AES_cbc_encrypt前,將源資料串進行了填充。