Android AES的ECB和CTR加解密代码实现

简而言之:

  1. CTR是在对称加密的基础上,对原文填充偏移解密后的输出结果和原文再异或 得到密文,一般结果用十六进制输出
  2. ECB是在对称加密的基础上,将原文分成若干个段,对每个段进行加密,每个段的输出结果 合起来就是最后的密文,最后的密文一般用 Base64 输出

在Android中的实现就是先导入:

implementation 'org.apache.shiro:shiro-core:1.2.2'

这个包最新的Android导入会出现 一样的类Load不了,我懒得解决,就换成低版本的包了。

这边CTR用的是PKS5Padding填充,也就是你 原文的bytes不是8或者16的倍数,会自动帮你用pks5填充
而ECB是NoPadding,也就是无填充,在加密之前,你必须保证原文是16的倍数,如果不是的话你可以用你和后台协商好的字符填充,就比如我这里的"\0"填充

    /**
     * AES CRT加密
     * 填充为PKCS5
     *
     * @param content 要加密的内容
     * @param key     加密文件的秘钥
     * @param iv      加密的偏移量
     * @return 输出Hex十六进制再次加密的结果
     **/
    public static String encryptCRT(byte[] content, String key, String iv) {
        String encodeStr = "";
        try {
            //产生密钥
            byte[] keyBytes = key.getBytes();
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
            //构建Cipher对象,需要传入一个字符串,格式必须为"algorithm/mode/padding"或者"algorithm/",意为"算法/加密模式/填充方式"
            Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
            //初始化Cipher对象
            byte[] ivBytes = iv.getBytes();
            IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            //加密数据
            byte[] resultBytes = cipher.doFinal(content);
            //结果用Hex十六进制转码
            encodeStr = new String(Hex.encode(resultBytes));
            return encodeStr;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return encodeStr;
    }

    /**
     * AES CTR 解密
     * 填充为PKCS5
     *
     * @param encode 加密过后的文件
     * @param iv     偏移量
     * @param key    秘钥文件
     */
    public static String decryptCRT(String encode, String iv, String key) {
        String decoded = "";
        try {
            byte[] bytes = Hex.decode(encode);
            IvParameterSpec ivSpec = new IvParameterSpec(
                    iv.getBytes());
            Key keys = new SecretKeySpec(key.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, keys, ivSpec);
            byte[] ret = cipher.doFinal(bytes);
            decoded = new String(ret);
            return decoded.trim();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return decoded;
    }

    /**
     * AES ECB加密
     * 填充为 “\0” noPadding
     *
     * @param content 要加密的内容
     * @param key     加密文件的秘钥
     * @return 输出Base64的结果
     **/
    public static String encryptECB(byte[] content, String key) {
        String encodeStr = "";
        try {
            byte[] keyBytes = key.getBytes();
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            //加密数据
            int length = content.length;
            int add = 16 - length % 16;
            if (add == 16) {
                add = 0;
            }
            byte[] contentNew = new byte[length + add];
            //用'\0'加密
            for (int i = 0; i < length + add; i++) {
                if (i < length) {
                    contentNew[i] = content[i];
                } else {
                    contentNew[i] = '\0' ;
                }
            }
            byte[] resultBytes = cipher.doFinal(contentNew);
            //结果用Base64
            encodeStr = new String(Base64Util.encode(resultBytes));
            return encodeStr;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return encodeStr;
    }

    /**
     * AES ECB解密
     *
     * @param encode 加密过后的文件
     * @param key    秘钥文件
     */
    public static String decryptECB(String encode, String key) {
        String decoded = "";
        byte[] decodeBase64 = Base64.decode(encode);
        int length = decodeBase64.length;
        int add = 16 - length % 16;
        if (add == 16) {
            add = 0;
        }
        byte[] decodeContentNew = new byte[length + add];
        //填充'\0'
        for (int i = 0; i < length + add; i++) {
            if (i < length) {
                decodeContentNew[i] = decodeBase64[i];
            } else {
                decodeContentNew[i] = '\0' ;
            }
        }
        try {
            Key keys = new SecretKeySpec(key.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, keys);
            byte[] ret = cipher.doFinal(decodeContentNew);
            decoded = new String(ret);
            return decoded.trim();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return decoded;
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在iOS中使用OpenSSL实现AES-GCM和ECB加密解密需要以下步骤: 1. 下载OpenSSL库并将其添加到iOS项目中。 2. 导入OpenSSL库头文件: ```objc #import <openssl/evp.h> #import <openssl/aes.h> ``` 3. 实现AES-GCM加密解密: ```objc // AES-GCM加密 + (NSData *)AESGCMEncryptWithKey:(NSData *)key iv:(NSData *)iv aad:(NSData *)aad plainText:(NSData *)plainText tagLength:(NSUInteger)tagLength { EVP_CIPHER_CTX *ctx; int len, outlen; unsigned char *outbuf; NSData *tag = nil; NSData *cipherText = nil; // 初始化EVP_CIPHER_CTX ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); // 设置key和iv EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)iv.length, NULL); EVP_EncryptInit_ex(ctx, NULL, NULL, key.bytes, iv.bytes); // 设置aad EVP_EncryptUpdate(ctx, NULL, &len, aad.bytes, (int)aad.length); // 加密明文 outbuf = malloc(plainText.length + AES_BLOCK_SIZE); EVP_EncryptUpdate(ctx, outbuf, &len, plainText.bytes, (int)plainText.length); cipherText = [NSData dataWithBytes:outbuf length:len]; free(outbuf); // 获取tag outbuf = malloc(tagLength); EVP_EncryptFinal_ex(ctx, outbuf, &outlen); tag = [NSData dataWithBytes:outbuf length:outlen]; free(outbuf); // 释放EVP_CIPHER_CTX EVP_CIPHER_CTX_free(ctx); // 返回加密结果和tag NSMutableData *resultData = [NSMutableData dataWithData:cipherText]; [resultData appendData:tag]; return resultData; } // AES-GCM解密 + (NSData *)AESGCMDecryptWithKey:(NSData *)key iv:(NSData *)iv aad:(NSData *)aad cipherText:(NSData *)cipherText tagLength:(NSUInteger)tagLength { EVP_CIPHER_CTX *ctx; int len, outlen; unsigned char *outbuf; NSData *tag = nil; NSData *plainText = nil; // 初始化EVP_CIPHER_CTX ctx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); // 设置key和iv EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, (int)iv.length, NULL); EVP_DecryptInit_ex(ctx, NULL, NULL, key.bytes, iv.bytes); // 设置aad EVP_DecryptUpdate(ctx, NULL, &len, aad.bytes, (int)aad.length); // 解密密文 outbuf = malloc(cipherText.length); EVP_DecryptUpdate(ctx, outbuf, &len, cipherText.bytes, (int)cipherText.length - tagLength); plainText = [NSData dataWithBytes:outbuf length:len]; free(outbuf); // 获取tag tag = [cipherText subdataWithRange:NSMakeRange(cipherText.length - tagLength, tagLength)]; EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, (int)tag.length, (void *)tag.bytes); // 验证tag if (EVP_DecryptFinal_ex(ctx, NULL, &outlen) <= 0) { return nil; // tag验证失败 } // 释放EVP_CIPHER_CTX EVP_CIPHER_CTX_free(ctx); // 返回解密结果 return plainText; } ``` 4. 实现ECB加密解密: ```objc // ECB加密 + (NSData *)ECBEncryptWithKey:(NSData *)key plainText:(NSData *)plainText { EVP_CIPHER_CTX *ctx; int len; unsigned char *outbuf; NSData *cipherText = nil; // 初始化EVP_CIPHER_CTX ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key.bytes, NULL); // 加密明文 outbuf = malloc(plainText.length + AES_BLOCK_SIZE); EVP_EncryptUpdate(ctx, outbuf, &len, plainText.bytes, (int)plainText.length); cipherText = [NSData dataWithBytes:outbuf length:len]; free(outbuf); // 释放EVP_CIPHER_CTX EVP_CIPHER_CTX_free(ctx); // 返回加密结果 return cipherText; } // ECB解密 + (NSData *)ECBDecryptWithKey:(NSData *)key cipherText:(NSData *)cipherText { EVP_CIPHER_CTX *ctx; int len; unsigned char *outbuf; NSData *plainText = nil; // 初始化EVP_CIPHER_CTX ctx = EVP_CIPHER_CTX_new(); EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key.bytes, NULL); // 解密密文 outbuf = malloc(cipherText.length); EVP_DecryptUpdate(ctx, outbuf, &len, cipherText.bytes, (int)cipherText.length); plainText = [NSData dataWithBytes:outbuf length:len]; free(outbuf); // 释放EVP_CIPHER_CTX EVP_CIPHER_CTX_free(ctx); // 返回解密结果 return plainText; } ``` 以上就是使用OpenSSL实现AES-GCM和ECB加密解密的步骤,需要注意的是,在iOS13及以上版本中,Apple已经将OpenSSL库废弃,推荐使用自带的CryptoKit框架实现加密解密。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值