Implementación de cifrado y descifrado AES para intercomunicación iOS JAVA

Antecedentes: debido a las necesidades comerciales, los enlaces en las páginas móviles deben cifrarse y descifrarse. Una vez que se completa el cifrado de back-end, el front-end (iOS, Android) se descifra. Android se descifró con éxito con la clave, y se hizo en diez minutos (esto no es fácil ~). iOS toma la clave para descifrar, o bien el descifrado da como resultado caracteres ilegibles o ninguno, y no se ha hecho después de medio día (Q realmente empatado).

A continuación se muestra el código que se ha descifrado con éxito a través de esfuerzos incansables. iOS, Android y JAVA pueden cifrarse y descifrarse entre sí, y copiarlo y usarlo directamente si es necesario.

1. Cifrado y descifrado de iOS

AESUtil.h

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCryptor.h>
NS_ASSUME_NONNULL_BEGIN

@interface AESUtil : NSObject

/**
 * AES加密
 */
+ (NSString *)encryptAES:(NSString *)content;
 
/**
 * AES解密
 */
+ (NSString *)decryptAES:(NSString *)content;


@end

NS_ASSUME_NONNULL_END

2、AESUtil.m

#import "AESUtil.h"

//key
static NSString *const PSW_AES_KEY = @"--32位字母数字组成的字符串--";
//偏移量
NSString *const kInitVector = @"--16位字母数字组成的字符串--";
//密钥长度
size_t const kKeySize = kCCKeySizeAES256;//kCCKeySizeAES128
@implementation AESUtil

+ (NSString *)encryptAES:(NSString *)content {
    NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger dataLength = contentData.length;
    // 为结束符'\\0' +1
    char keyPtr[kKeySize + 1];
    memset(keyPtr, 0, sizeof(keyPtr));
    [PSW_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    // 密文长度 <= 明文长度 + BlockSize
    size_t encryptSize = dataLength + kCCBlockSizeAES128;
    void *encryptedBytes = malloc(encryptSize);
    size_t actualOutSize = 0;
    NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding];
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES,
                                          kCCOptionPKCS7Padding,  // 系统默认使用 CBC,使用 PKCS7Padding
                                          keyPtr,
                                          kKeySize,
                                          initVector.bytes,
                                          contentData.bytes,
                                          dataLength,
                                          encryptedBytes,
                                          encryptSize,
                                          &actualOutSize);
    if (cryptStatus == kCCSuccess) {
        // 对加密后的数据 base64 编码
        return [[NSData dataWithBytesNoCopy:encryptedBytes length:actualOutSize] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    }
    free(encryptedBytes);
    return nil;
}

+ (NSString *)decryptAES:(NSString *)content{
    NSData *contentData = [[NSData alloc] initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
    NSUInteger dataLength = contentData.length;
    char keyPtr[kKeySize + 1];
    memset(keyPtr, 0, sizeof(keyPtr));
    [PSW_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    size_t decryptSize = dataLength + kCCBlockSizeAES128;
    void *decryptedBytes = malloc(decryptSize);
    size_t actualOutSize = 0;
    NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding];
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          kCCAlgorithmAES,
                                          kCCOptionPKCS7Padding,
                                          keyPtr,
                                          kKeySize,
                                          initVector.bytes,
                                          contentData.bytes,
                                          dataLength,
                                          decryptedBytes,
                                          decryptSize,
                                          &actualOutSize);
    if (cryptStatus == kCCSuccess) {
        return [[NSString alloc] initWithData:[NSData dataWithBytesNoCopy:decryptedBytes length:actualOutSize] encoding:NSUTF8StringEncoding];
    }
    free(decryptedBytes);
    return nil;
}

@end

Nota: La cadena descifrada contiene el carácter invisible "\0", que debe reemplazarse con "", de la siguiente manera

NSString *result = [decryptContent stringByReplacingOccurrencesOfString:@"\0" withString:@""];

Dos, Android, cifrado y descifrado JAVA

public class AESUtil {
    private static final String AES = "AES";
    private static final String Mode = "AES/CBC/PKCS5Padding";

    private static Cipher cipherEncrypt;
    private static Cipher cipherDecrypt;
    /**
      * AES加密
      */
    public static String encrypt(String aPlaintext, String aKey) {
        String originalString = "";
        try {
            String tmpIv = aKey.substring(16, 32);
            SecretKeySpec keyspec = new SecretKeySpec(aKey.getBytes(), AES);
            IvParameterSpec ivspec = new IvParameterSpec(tmpIv.getBytes());
            cipherEncrypt = Cipher.getInstance(Mode);
            cipherEncrypt.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

            byte[] encrypted = null;
            int blockSize = cipherEncrypt.getBlockSize();
            byte[] dataBytes = aPlaintext.getBytes();
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

            try {
                encrypted = cipherEncrypt.doFinal(plaintext);
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
            if (encrypted == null) {
                LogUtils.e("算法加密错误!返回无结果");
                return null;
            }
            originalString = Base64.encodeToString(encrypted, Base64.DEFAULT);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }

        return originalString.trim();
    }
    /**
      * AES解密
      */
    public static String decrypt(String aCiphertext, String aKey) {
        String originalString = "";
        try {
            String tmpIv = aKey.substring(16, 32);
            SecretKeySpec keyspec = new SecretKeySpec(aKey.getBytes(), AES);
            IvParameterSpec ivspec = new IvParameterSpec(tmpIv.getBytes());
            cipherDecrypt = Cipher.getInstance(Mode);
            cipherDecrypt.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] sourcebyte = Base64.decode(aCiphertext, Base64.DEFAULT);
            byte[] original = null;
            original = cipherDecrypt.doFinal(sourcebyte);
            try {
                originalString = new String(original, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            LogUtils.e("设置算法错误!");
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            LogUtils.e("解密算法密钥设置错误!");
            LogUtils.e("解密算法密钥长度不够,过长!");
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            LogUtils.e("算法解密过程错误!");
            LogUtils.e("块大小设置错误!密文长度不够或太长!");
            e.printStackTrace();
        } catch (BadPaddingException e) {
            LogUtils.e("解密算法解密过程错误!");
            LogUtils.e("解密填充方式错误!");
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        return originalString.trim();
    }
}

Si el artículo es útil para usted, no olvide darle un pulgar hacia arriba ~

Supongo que te gusta

Origin blog.csdn.net/c_furong/article/details/127265137
Recomendado
Clasificación