AES加密Android< - > iOS不同的结果上的消息长度> 15字节 [英] AES Encryption Android <-> iOS different results on message length > 15 byte

查看:322
本文介绍了AES加密Android< - > iOS不同的结果上的消息长度> 15字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在理解两个设备上的密码/密码时遇到了一个真正的问题。

I got a real problem in understanding the cipher/crypter on both devices.

1。
如果我们在iOS和Android上使用Cipher AES对消息进行加密,并且字符串的字符长度不大于16(例如abcdefghijklmno),那么在使用相同的密钥/密码加密后,我们得到了相同的结果。

1. If we encrypt a message on iOS and on Android using Cipher AES and the charlength of the string is not bigger than 16 (eg. "abcdefghijklmno") we got the same result after encrypting it with the same key/password.

2。
但是如果需要更长的消息,我们会在iOS和Android上获得不同的结果(例如abcdefghijklmnop)

2. But if take a longer message we get different results on iOS and Android (eg. "abcdefghijklmnop")

我做了很多研究,

这是我的加密密码:

public String encode(Context context, String password, String text)
        throws NoPassGivenException, NoTextGivenException {
    if (password.length() == 0 || password == null) {
        throw new NoPassGivenException("Please give Password");
    }

    if (text.length() == 0 || text == null) {
        throw new NoTextGivenException("Please give text");
    }

    try {
        SecretKeySpec skeySpec = getKey(password);
        byte[] clearText = text.getBytes("UTF8");


        //IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
        final byte[] iv = new byte[16];
        Arrays.fill(iv, (byte) 0x00);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

        // Cipher is not thread safe
                    //EDITED AFTER RIGHT ANSWER FROM
                    //*** Cipher cipher = Cipher.getInstance("AES");   ***//
                    // TO  
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");


        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);

        String encrypedValue = Base64.encodeToString(
                cipher.doFinal(clearText), Base64.DEFAULT);
        Log.d(TAG, "Encrypted: " + text + " -> " + encrypedValue);
        return encrypedValue;

    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }
    return "";
}


public SecretKeySpec getKey(String password)
        throws UnsupportedEncodingException {


    int keyLength = 128;
    byte[] keyBytes = new byte[keyLength / 8];
    // explicitly fill with zeros
    Arrays.fill(keyBytes, (byte) 0x0);

    // if password is shorter then key length, it will be zero-padded
    // to key length
    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;
}

这里是我的同事的iOS吊坠:

And here is the iOS pendant from my collegue:

- (NSData *)AES128EncryptWithKey:(NSString *)key {

    // 'key' should be 32 bytes for AES256,
    // 16 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES128 + 1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // insert key in char array
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;

    // the encryption method, use always same attributes in android and iPhone (f.e. PKCS7Padding)
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding,
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          NULL                      /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize,       /* output */
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {

        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer);
    return nil;
}

我真的很想了解什么是差异,以及如何避免它。测试,确切与更大的字符串15个字符给我一个提示,但我不知道为什么:)

I really like to understand what the difference could be and how to avoid it. The testing that exact with bigger Strings than 15 characters gave me a hint but i do not know why :)

感谢在先进的家伙!

推荐答案

检查两个系统上正在使用的填充。不同的填充将导致不同的输出。不要依赖默认值,而是明确设置两边的填充。您的第二个代码片段显式设置PKCS7填充。

Check what padding is being used on both systems. Different padding will result in different output. Do not rely on defaults but explicitly set the padding on both sides. Your second code fragment explicitly sets PKCS7 padding. Use that on both ends.

作为一般规则,依赖于不同系统之间的默认值。显式设置IV,模式,填充,随机数或任何其他需要。 Crypto设计为即使最细微的细节不匹配也会失败。

As a general rule, do not rely on defaults between different systems. Explicitly set the IV, mode, padding, nonce or whatever else is needed. Crypto is designed to fail badly if even the slightest detail does not match.

这篇关于AES加密Android&lt; - &gt; iOS不同的结果上的消息长度&gt; 15字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆