美文网首页
AES加密解密 -- iOS、Java之间的互相通信

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

作者: 一个不太努力的代码搬运工 | 来源:发表于2017-08-07 17:21 被阅读0次
    简介:AES是一种对称加密方式,旨在取代DES成为广泛使用的标准。虽然语言不同,但是AES的算法是相同的。

    关于AES的各种参数请参考下面文章(一定要认真阅读,不然就没办法按照自己的想法进行加密解密):AES加密 - iOS与Java的同步实现

    思路:

    先说一下我的想法,iOS端加密由Java解密,Java加密由iOS解密,加密模式采取CBC,密钥长度为256位,初始向量(相当于是加密解密规则)为32位,这个是要对应密钥长度的。

    难点:

    1、Java对于大于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才会支持256位的密钥加密。
    2、iOS端的kKeySize改为kCCKeySizeAES256
    3、两端的key(加密解密规则)设置成32位字符串。
    实现:
    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);
    }
    

    先自行测试一下:

        NSString *plainText = @"战狼2";
        //32位key,加解密规则
        NSString *key = @"16-Bytes--String16-Bytes--String";
        
        NSString *cipherText = aesEncryptString(plainText, key);
        
        NSLog(@"%@", cipherText);
        
        NSString *decryptedText = aesDecryptString(cipherText, key);
        
        NSLog(@"%@", decryptedText);
    

    测试结果:

    2017-08-07 17:04:07.346 AES加解密[1936:131257] BOtqpCDe2AcRw2sbt4+F9w==
    2017-08-07 17:04:07.348 AES加解密[1936:131257] 战狼2
    
    Java端:

    一定要记得导入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);
        }
    
    }
    

    测试:

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

    结果:

    BOtqpCDe2AcRw2sbt4+F9w==
    战狼2
    
    两端之间的通信:

    由上面测试结果可以看出,相同的加密规则,相同的加密内容,加密之后的结果是相同的。所以无论是iOS端加密,Java端解密 还是Java端加密,iOS端解密,都是可以实现的。

    相关文章

      网友评论

          本文标题:AES加密解密 -- iOS、Java之间的互相通信

          本文链接:https://www.haomeiwen.com/subject/nddalxtx.html