Java AES加密 iOS解密

最近做項(xiàng)目,需要服務(wù)器(java寫的)進(jìn)行AES加密,然后iOS解密。這是背景,然后就出現(xiàn)了java AES加密,iOS解密不成功的問題。

網(wǎng)上的說法:發(fā)現(xiàn)在java端和iOS端采用相同明文,相同密鑰加密后的密文不一樣!上網(wǎng)查了資料后發(fā)現(xiàn)iOS中AES加密算法采用的填充是PKCS7Padding,而java不支持PKCS7Padding,只支持PKCS5Padding。我們知道加密算法由算法+模式+填充組成,所以這兩者不同的填充算法導(dǎo)致相同明文相同密鑰加密后出現(xiàn)密文不一致的情況。那么我們需要在java中用PKCS7Padding來填充,這樣就可以和iOS端填充算法一致了。要實(shí)現(xiàn)在java端用PKCS7Padding填充,需要用到bouncycastle組件來實(shí)現(xiàn)。

但是,我不想用bouncycastle,因此就采用了AES/ECB/PKCS5Padding來加密,但是AES/ECB/PKCS5Padding在java中只支持128AES加密。

下面就是我自己的解決方案,話不多說了,直接上java服務(wù)器代碼和iOS客戶端代碼。

  • java服務(wù)端代碼
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AESCrypt {

    /**
     * 對(duì)字符串加密
     *
     * @param str 加密明文
     * @param key 加密秘鑰
     * @return 加密密文
     */
    public static String Encrytor(String str, String key) {
        try {
            byte[] raw = key.getBytes("utf-8");
            SecretKeySpec spec = new SecretKeySpec(raw, "AES");
            Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
            c.init(Cipher.ENCRYPT_MODE, spec);
            byte[] src = str.getBytes("utf-8");
            byte[] cipherByte = c.doFinal(src);
            return new BASE64Encoder().encode(cipherByte);
            //return AESCrypt.encodeBase64(cipherByte);
            //return bytesToString(cipherByte);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 對(duì)字符串解密
     *
     * @param  str 解密密文
     * @param key 解密秘鑰
     * @return 解密明文
     */
    public static String Decryptor(String str, String key) {
        try {
            byte[] raw = key.getBytes("utf-8");
            SecretKeySpec spec = new SecretKeySpec(raw, "AES");
            Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
            c.init(Cipher.DECRYPT_MODE, spec);
            byte[] src = new BASE64Decoder().decodeBuffer(str);
            byte[] cipherByte = c.doFinal(src);
            return new String(cipherByte, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        try {
            String password = "123456";
            String secretKey = "1234567812345678";
            System.out.println(secretKey.length());
            System.out.println("SecretKey=" + secretKey);
            String encodePwd = AESCrypt.Encrytor(password, secretKey);
            System.out.println("encodePwd=" + encodePwd);
            String decodePwd = AESCrypt.Decryptor(encodePwd, secretKey);
            System.out.println("decodePwd=" + decodePwd);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

注意項(xiàng):
設(shè)置加密形式
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
可以設(shè)置
String secretKey = "1234567812345678"; 必須為16位。

  • iOS客戶端代碼
  + (NSString *)aes128DecryptWithText:(NSString *)codeStr key:(NSString *)keyStr{
    if (codeStr == nil) return @"";
    NSData *cipherData = [self dataWithBase64EncodedString:codeStr];
    char keyPtr[kCCKeySizeAES128+1];
    bzero(keyPtr, sizeof(keyPtr));
    [keyStr getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    size_t bufferSize = [cipherData length] + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionECBMode|kCCOptionPKCS7Padding,
                                          keyPtr,
                                          kCCKeySizeAES128,NULL,
                                          [cipherData bytes],[cipherData length],
                                          buffer, bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *encryptData = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        return [[NSString alloc] initWithData:encryptData encoding:NSUTF8StringEncoding];
    }
    
    free(buffer);
    return nil;
}

調(diào)用

 NSString * aesDecryptStr = [NSData aes128DecryptWithText:@"mdSm0RmB+xAKrTah3DG31A==" key:"1234567812345678"];

over,希望對(duì)大家有所幫助。

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

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

  • 概述 之前一直對(duì)加密相關(guān)的算法知之甚少,只知道類似DES、RSA等加密算法能對(duì)數(shù)據(jù)傳輸進(jìn)行加密,且各種加密算法各有...
    Henryzhu閱讀 3,208評(píng)論 0 14
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home...
    光劍書架上的書閱讀 4,178評(píng)論 2 8
  • 引言 如今手機(jī)app五彩繽紛,確保手機(jī)用戶的數(shù)據(jù)安全是開發(fā)人員必須掌握的技巧,下面通過實(shí)例介紹DES在androi...
    freesan44閱讀 1,228評(píng)論 1 1
  • 感想 今天沒有音頻,主要是在群里交流,閱讀文章。說的內(nèi)容好像都是《窮爸爸,富爸爸》里的。這書我是看過的, 當(dāng)初差點(diǎn)...
    青木729閱讀 242評(píng)論 0 0

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