在Android和IPhone中使用AES 256进行加密(不同的结果)

在Android和IPhone中使用AES 256进行加密(不同的结果),第1张

概述我试图通过引用IOS实现在Android平台上实现客户端加密/解密.我正在努力解决Android和IOS平台上的加密和解密不同的问题,即使他们使用相同的算法.假设,当Android设备加密并将文件上传到服务器时,IOS设备无法正确下载和解密.我正在使用的算法>使用用户提供的密码加密文件密钥.我们

我试图通过引用IOS实现在Android平台上实现客户端加密/解密.我正在努力解决AndroID和IOS平台上的加密和解密不同的问题,即使他们使用相同的算法.假设,当AndroID设备加密并将文件上传到服务器时,IOS设备无法正确下载和解密.

我正在使用的算法

>使用用户提供的密码加密文件密钥.我们首先使用PBKDF2算法(SHA256的1000次迭代)从密码中导出密钥/ iv对,然后使用AES 256 / CBC加密文件密钥.结果称为“加密文件密钥”.此加密文件密钥将被发送并存储在服务器上.当您需要访问数据时,可以从加密文件密钥解密文件密钥.
>所有文件数据均由AES 256 / CBC的文件密钥加密.我们使用PBKDF2算法(SHA256的1000次迭代)从文件密钥中导出密钥/ iv对.
>在本地存储派生的密钥/ iv对,并使用它们来加密文件.加密后,数据将上载​​到服务器.下载文件时与解密文件相同.

AndroID代码

    private static final String TAG = Crypto.class.getSimplename();    private static final String CIPHER_ALGORITHM = "AES/CBC/Nopadding";    private static int KEY_LENGTH = 32;    private static int KEY_LENGTH_SHORT = 16;    // minimum values recommended by PKCS#5, increase as necessary    private static int IteraTION_COUNT = 1000;    // Should generate random salt for each repo    private static byte[] salt = {(byte) 0xda, (byte) 0x90, (byte) 0x45, (byte) 0xc3, (byte) 0x06, (byte) 0xc7, (byte) 0xcc, (byte) 0x26};    private Crypto() {    }    /**     * decrypt repo encKey     *     * @param password     * @param randomKey     * @param version     * @return     * @throws UnsupportedEnCodingException     * @throws NoSuchAlgorithmException     */    public static String deriveKeyPbkdf2(String password, String randomKey, int version) throws UnsupportedEnCodingException, NoSuchAlgorithmException {        if (TextUtils.isEmpty(password) || TextUtils.isEmpty(randomKey)) {            return null;        }        PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());        gen.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password.tochararray()), salt, IteraTION_COUNT);        byte[] keyBytes;        if (version == 2) {            keyBytes = ((KeyParameter) gen.generateDerivedMacParameters(KEY_LENGTH * 8)).getKey();        } else            keyBytes = ((KeyParameter) gen.generateDerivedMacParameters(KEY_LENGTH_SHORT * 8)).getKey();        SecretKey realKey = new SecretKeySpec(keyBytes, "AES");        final byte[] iv = deriveIVPbkdf2(realKey.getEncoded());        return seafileDecrypt(fromHex(randomKey), realKey, iv);    }    public static byte[] deriveIVPbkdf2(byte[] key) throws UnsupportedEnCodingException {        PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());        gen.init(key, salt, 10);        return ((KeyParameter) gen.generateDerivedMacParameters(KEY_LENGTH_SHORT * 8)).getKey();    }    /**     * All file data is encrypted by the file key with AES 256/CBC.     *     * We use PBKDF2 algorithm (1000 iterations of SHA256) to derive key/iv pair from the file key.     * After encryption, the data is uploaded to the server.     *     * @param plaintext     * @param key     * @return     */    private static byte[] seafileEncrypt(byte[] plaintext, SecretKey key, byte[] iv) {        try {            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);            IvParameterSpec ivParams = new IvParameterSpec(iv);            cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);            return cipher.doFinal(plaintext);        } catch (NoSuchAlgorithmException e) {            e.printstacktrace();            Log.e(TAG, "NoSuchAlgorithmException " + e.getMessage());            return null;        } catch (InvalIDKeyException e) {            e.printstacktrace();            Log.e(TAG, "InvalIDKeyException " + e.getMessage());            return null;        } catch (InvalIDAlgorithmParameterException e) {            e.printstacktrace();            Log.e(TAG, "InvalIDAlgorithmParameterException " + e.getMessage());            return null;        } catch (NoSuchpaddingException e) {            e.printstacktrace();            Log.e(TAG, "NoSuchpaddingException " + e.getMessage());            return null;        } catch (IllegalBlockSizeException e) {            e.printstacktrace();            Log.e(TAG, "IllegalBlockSizeException " + e.getMessage());            return null;        } catch (BadpaddingException e) {            e.printstacktrace();            Log.e(TAG, "BadpaddingException " + e.getMessage());            return null;        }    }    /**     * All file data is encrypted by the file key with AES 256/CBC.     *     * We use PBKDF2 algorithm (1000 iterations of SHA256) to derive key/iv pair from the file key.     * After encryption, the data is uploaded to the server.     *     * @param plaintext     * @param key     * @return     */    public static byte[] encrypt(byte[] plaintext, String key, byte[] iv, int version) throws NoSuchAlgorithmException {        PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());        gen.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(key.tochararray()), salt, IteraTION_COUNT);        byte[] keyBytes;        if (version == 2) {            keyBytes = ((KeyParameter) gen.generateDerivedMacParameters(KEY_LENGTH * 8)).getKey();        } else            keyBytes = ((KeyParameter) gen.generateDerivedMacParameters(KEY_LENGTH_SHORT * 8)).getKey();        SecretKey realKey = new SecretKeySpec(keyBytes, "AES");        return seafileEncrypt(plaintext, realKey , iv);    }

IOS代码

+ (int)deriveKey:(const char *)data_in inlen:(int)in_len version:(int)version key:(unsigned char *)key iv:(unsigned char *)iv{    unsigned char salt[8] = { 0xda, 0x90, 0x45, 0xc3, 0x06, 0xc7, 0xcc, 0x26 };    if (version == 2) {        PKCS5_PBKDF2_HMAC (data_in, in_len,                           salt, sizeof(salt),                           1000,                           EVP_sha256(),                           32, key);        PKCS5_PBKDF2_HMAC ((char *)key, 32,                           salt, sizeof(salt),                           10,                           EVP_sha256(),                           16, iv);        return 0;    } else if (version == 1)        return EVP_BytesToKey (EVP_aes_128_cbc(), /* cipher mode */                               EVP_sha1(),        /* message digest */                               salt,              /* salt */                               (unsigned char*)data_in,                               in_len,                               1 << 19,   /* iteration times */                               key, /* the derived key */                               iv); /* IV, initial vector */    else        return EVP_BytesToKey (EVP_aes_128_ecb(), /* cipher mode */                               EVP_sha1(),        /* message digest */                               NulL,              /* salt */                               (unsigned char*)data_in,                               in_len,                               3,   /* iteration times */                               key, /* the derived key */                               iv); /* IV, initial vector */}+(int)seafileEncrypt:(char **)data_out outlen:(int *)out_len datain:(const char *)data_in inlen:(const int)in_len version:(int)version key:(uint8_t *)key iv:(uint8_t *)iv{    int ret, blks;    EVP_CIPHER_CTX ctx;    EVP_CIPHER_CTX_init (&ctx);    if (version == 2)        ret = EVP_Encryptinit_ex (&ctx,                                  EVP_aes_256_cbc(), /* cipher mode */                                  NulL, /* engine, NulL for default */                                  key,  /* derived key */                                  iv);  /* initial vector */    else if (version == 1)        ret = EVP_Encryptinit_ex (&ctx,                                  EVP_aes_128_cbc(), /* cipher mode */                                  NulL, /* engine, NulL for default */                                  key,  /* derived key */                                  iv);  /* initial vector */    else        ret = EVP_Encryptinit_ex (&ctx,                                  EVP_aes_128_ecb(), /* cipher mode */                                  NulL, /* engine, NulL for default */                                  key,  /* derived key */                                  iv);  /* initial vector */    if (ret == DEC_FAILURE)        return -1;    blks = (in_len / BLK_SIZE) + 1;    *data_out = (char *)malloc (blks * BLK_SIZE);    if (*data_out == NulL) {        DeBUG ("Failed to allocate the output buffer.\n");        goto enc_error;    }    int update_len, final_len;    /* Do the encryption. */    ret = EVP_EncryptUpdate (&ctx,                             (unsigned char*)*data_out,                             &update_len,                             (unsigned char*)data_in,                             in_len);    if (ret == ENC_FAILURE)        goto enc_error;    /* Finish the possible partial block. */    ret = EVP_EncryptFinal_ex (&ctx,                               (unsigned char*)*data_out + update_len,                               &final_len);    *out_len = update_len + final_len;    /* out_len should be equal to the allocated buffer size. */    if (ret == ENC_FAILURE || *out_len != (blks * BLK_SIZE))        goto enc_error;    EVP_CIPHER_CTX_cleanup (&ctx);    return 0;enc_error:    EVP_CIPHER_CTX_cleanup (&ctx);    *out_len = -1;    if (*data_out != NulL)        free (*data_out);    *data_out = NulL;    return -1;}+ (voID)generateKey:(Nsstring *)password version:(int)version encKey:(Nsstring *)encKey key:(uint8_t *)key iv:(uint8_t *)iv{    unsigned char key0[32], iv0[16];    char passwordPtr[256] = {0}; // room for terminator (unused)    [password getCString:passwordPtr maxLength:sizeof(passwordPtr) enCoding:NSUTF8StringEnCoding];    if (version < 2) {        [NSData deriveKey:passwordPtr inlen:(int)password.length version:version key:key iv:iv];        return;    }    [NSData deriveKey:passwordPtr inlen:(int)password.length version:version key:key0 iv:iv0];    char enc_random_key[48], dec_random_key[48];    int outlen;    hex_to_rawdata(encKey.UTF8String, enc_random_key, 48);    [NSData seafileDecrypt:dec_random_key outlen:&outlen datain:(char *)enc_random_key inlen:48 version:2 key:key0 iv:iv0];    [NSData deriveKey:dec_random_key inlen:32 version:2 key:key iv:iv];}- (NSData *)encrypt:(Nsstring *)password encKey:(Nsstring *)encKey version:(int)version{    uint8_t key[kCCKeySizeAES256+1] = {0}, iv[kCCKeySizeAES128+1];    [NSData generateKey:password version:version encKey:encKey key:key iv:iv];    char *data_out;    int outlen;    int ret = [NSData seafileEncrypt:&data_out outlen:&outlen datain:self.bytes inlen:(int)self.length version:version key:key iv:iv];    if (ret < 0) return nil;    return [NSData dataWithBytesNocopy:data_out length:outlen];}

对于发现此功能的人来说,这是一个完整的项目.

> Support client side encryption #487
> How does an encrypted library work?

解决方法:

嗨,我也有同样的问题.

我发现有两件事导致我的代码不匹配:
 1. ios和androID加密算法不一样(我已经在ios中请求了PKCS7padding算法,我在androID中尝试了Nopadding和AES / CBC / PKCS5padding算法.
 2. ios中生成的密钥与AndroID中的密钥不同.

请看我的工作代码在ios和androID中都提供相同的输出:

IOS:

- (Nsstring *) encryptString:(Nsstring*)plaintext withKey:(Nsstring*)key {NSData *data = [[plaintext dataUsingEnCoding:NSUTF8StringEnCoding] AES256EncryptWithKey:key];return [data base64EncodedStringWithOptions:kNilOptions];}- (Nsstring *) decryptString:(Nsstring *)ciphertext withKey:(Nsstring*)key {if ([ciphertext isKindOfClass:[Nsstring class]]) {     NSData *data = [[NSData alloc] initWithBase64EncodedString:ciphertext options:kNilOptions];    return [[Nsstring alloc] initWithData:[data AES256DecryptWithKey:key] enCoding:NSUTF8StringEnCoding];}return nil;}

AndroID :(我们修改了aes w.r.t iOS默认方法)

private static String Key = "your key"; public static String encryptString(String stringToEncode) throws NullPointerException {    try {        SecretKeySpec skeySpec = getKey(Key);        byte[] clearText = stringToEncode.getBytes("UTF8");        final byte[] iv = new byte[16];        Arrays.fill(iv, (byte) 0x00);        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7padding");        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);        String encrypedValue = Base64.encodetoString(cipher.doFinal(clearText), Base64.DEFAulT);        return encrypedValue;    } catch (Exception e) {        e.printstacktrace();    }    return "";}public static String encryptString(String stringToEncode) throws NullPointerException {    try {        SecretKeySpec skeySpec = getKey(Key);        byte[] clearText = stringToEncode.getBytes("UTF8");        final byte[] iv = new byte[16];        Arrays.fill(iv, (byte) 0x00);        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7padding");        cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);        byte[] cipherData = cipher.doFinal(Base64.decode(stringToEncode.getBytes("UTF-8"), Base64.DEFAulT));        String decoded = new String(cipherData, "UTF-8");        return decoded;    } catch (Exception e) {        e.printstacktrace();    }    return "";}private static SecretKeySpec getKey(String password) throws UnsupportedEnCodingException {    int keyLength = 256;    byte[] keyBytes = new byte[keyLength / 8];    Arrays.fill(keyBytes, (byte) 0x0);    byte[] passwordBytes = password.getBytes("UTF-8");    int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length;    System.arraycopy(passwordBytes, 0, keyBytes, 0, length);    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");    return key;}

希望这有助于你们
谢谢

总结

以上是内存溢出为你收集整理的在Android和IPhone中使用AES 256进行加密(不同的结果)全部内容,希望文章能够帮你解决在Android和IPhone中使用AES 256进行加密(不同的结果)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1098111.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-28
下一篇2022-05-28

发表评论

登录后才能评论

评论列表(0条)

    保存