AES加密解密 -- iOS、Java之間的互相通信

簡介:AES是一種對(duì)稱加密方式,旨在取代DES成為廣泛使用的標(biāo)準(zhǔn)。雖然語言不同,但是AES的算法是相同的。

關(guān)于AES的各種參數(shù)請(qǐng)參考下面文章(一定要認(rèn)真閱讀,不然就沒辦法按照自己的想法進(jìn)行加密解密):AES加密 - iOS與Java的同步實(shí)現(xiàn)

思路:

先說一下我的想法,iOS端加密由Java解密,Java加密由iOS解密,加密模式采取CBC,密鑰長度為256位,初始向量(相當(dāng)于是加密解密規(guī)則)為32位,這個(gè)是要對(duì)應(yīng)密鑰長度的。

難點(diǎn):

1、Java對(duì)于大于128bits的是不支持的,我們需要將JDK中的local_policy.jar US_export_policy.jar這里的jar包替換掉,我的mac電腦,JDK路徑是資源庫/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/libsecurity

替換的jar包

這樣Java才會(huì)支持256位的密鑰加密。
2、iOS端的kKeySize改為kCCKeySizeAES256。
3、兩端的key(加密解密規(guī)則)設(shè)置成32位字符串。

實(shí)現(xiàn):
iOS端

AESCipher.h


@interface AESCipher : NSObject
NSString * aesEncryptString(NSString *content, NSString *key);
NSString * aesDecryptString(NSString *content, NSString *key);

NSData * aesEncryptData(NSData *data, NSData *key);
NSData * aesDecryptData(NSData *data, NSData *key);
@end

AESCipher.m

#import <CommonCrypto/CommonCryptor.h>

NSString const *kInitVector = @"A-16-Byte-String";
size_t const kKeySize = kCCKeySizeAES256;

NSData * cipherOperation(NSData *contentData, NSData *keyData, CCOperation operation) {
    NSUInteger dataLength = contentData.length;
    
    void const *initVectorBytes = [kInitVector dataUsingEncoding:NSUTF8StringEncoding].bytes;
    void const *contentBytes = contentData.bytes;
    void const *keyBytes = keyData.bytes;
    
    size_t operationSize = dataLength + kCCKeySizeAES256;
    void *operationBytes = malloc(operationSize);
    size_t actualOutSize = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES,
                                          kCCOptionPKCS7Padding,
                                          keyBytes,
                                          kKeySize,
                                          initVectorBytes,
                                          contentBytes,
                                          dataLength,
                                          operationBytes,
                                          operationSize,
                                          &actualOutSize);
    
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:operationBytes length:actualOutSize];
    }
    free(operationBytes);
    return nil;
}

NSString * aesEncryptString(NSString *content, NSString *key) {
    NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding];
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *encrptedData = aesEncryptData(contentData, keyData);
    return [encrptedData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
}

NSString * aesDecryptString(NSString *content, NSString *key) {
    NSData *contentData = [[NSData alloc] initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSData *decryptedData = aesDecryptData(contentData, keyData);
    return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
}

NSData * aesEncryptData(NSData *contentData, NSData *keyData) {
    NSString *hint = [NSString stringWithFormat:@"The key size of AES-%lu should be %lu bytes!", kKeySize * 8, kKeySize];
    NSCAssert(keyData.length == kKeySize, hint);
    return cipherOperation(contentData, keyData, kCCEncrypt);
}

NSData * aesDecryptData(NSData *contentData, NSData *keyData) {
    NSString *hint = [NSString stringWithFormat:@"The key size of AES-%lu should be %lu bytes!", kKeySize * 8, kKeySize];
    NSCAssert(keyData.length == kKeySize, hint);
    return cipherOperation(contentData, keyData, kCCDecrypt);
}

先自行測(cè)試一下:

    NSString *plainText = @"戰(zhàn)狼2";
    //32位key,加解密規(guī)則
    NSString *key = @"16-Bytes--String16-Bytes--String";
    
    NSString *cipherText = aesEncryptString(plainText, key);
    
    NSLog(@"%@", cipherText);
    
    NSString *decryptedText = aesDecryptString(cipherText, key);
    
    NSLog(@"%@", decryptedText);

測(cè)試結(jié)果:

2017-08-07 17:04:07.346 AES加解密[1936:131257] BOtqpCDe2AcRw2sbt4+F9w==
2017-08-07 17:04:07.348 AES加解密[1936:131257] 戰(zhàn)狼2
Java端:

一定要記得導(dǎo)入javabase64-1.3.1

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.io.UnsupportedEncodingException;
public class AESCipher {
    private static final String IV_STRING = "A-16-Byte-String";
    private static final String charset = "UTF-8";
     
    public static String aesEncryptString(String content, String key) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        byte[] contentBytes = content.getBytes(charset);
        byte[] keyBytes = key.getBytes(charset);
        byte[] encryptedBytes = aesEncryptBytes(contentBytes, keyBytes);
        Encoder encoder = Base64.getEncoder();
        return encoder.encodeToString(encryptedBytes);
    }

    public static String aesDecryptString(String content, String key) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        Decoder decoder = Base64.getDecoder();
        byte[] encryptedBytes = decoder.decode(content);
        byte[] keyBytes = key.getBytes(charset);
        byte[] decryptedBytes = aesDecryptBytes(encryptedBytes, keyBytes);
        return new String(decryptedBytes, charset);     
    }
    
    public static byte[] aesEncryptBytes(byte[] contentBytes, byte[] keyBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return cipherOperation(contentBytes, keyBytes, Cipher.ENCRYPT_MODE);
    }
    
    public static byte[] aesDecryptBytes(byte[] contentBytes, byte[] keyBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return cipherOperation(contentBytes, keyBytes, Cipher.DECRYPT_MODE);
    }
    
    private static byte[] cipherOperation(byte[] contentBytes, byte[] keyBytes, int mode) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
        
        byte[] initParam = IV_STRING.getBytes(charset);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(mode, secretKey, ivParameterSpec);

        return cipher.doFinal(contentBytes);
    }

}

測(cè)試:

String key = "16-Bytes--String16-Bytes--String";
        String encryptStr = AESCipher.aesEncryptString("戰(zhàn)狼2", key);
        System.out.println(encryptStr);
        String decryptStr = AESCipher.aesDecryptString(encryptStr, key);
        System.out.println(decryptStr);

結(jié)果:

BOtqpCDe2AcRw2sbt4+F9w==
戰(zhàn)狼2
兩端之間的通信:

由上面測(cè)試結(jié)果可以看出,相同的加密規(guī)則,相同的加密內(nèi)容,加密之后的結(jié)果是相同的。所以無論是iOS端加密,Java端解密 還是Java端加密,iOS端解密,都是可以實(shí)現(xiàn)的。

最后編輯于
?著作權(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)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,551評(píng)論 19 139
  • /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home...
    光劍書架上的書閱讀 4,183評(píng)論 2 8
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,013評(píng)論 25 709
  • 文/青蓮 一遍遍的翻看空間 尋找那些曾經(jīng)的記憶 回憶是如此蒼白 你還記得所有的曾經(jīng)嗎 老照片已經(jīng)泛黃 腦海的記憶也...
    青蓮蒼茫閱讀 239評(píng)論 0 0
  • 沒有幾句炫酷的英語口語,怎么出去震撼小伙伴啊!趕快跟春喜外語來看一看下面的25句炫酷的日常英語口語,你知道幾句呢?...
    春喜外語學(xué)堂閱讀 800評(píng)論 0 2

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