Android的AES密码加密基于使用的每封邮件的一个关键和随机IV [英] Android AES password-based encryption using one key and random IV for every message

查看:313
本文介绍了Android的AES密码加密基于使用的每封邮件的一个关键和随机IV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在实施在Android上使用AES 256对称加密/解密,通过这个帖子的启发:
Java的256位AES加密
我实施的目的是,我想在一个数据库中的数据进行加密。

I'm currently implementing a symmetric en-/decryption using AES 256 on Android, inspired by this post: Java 256bit AES Encryption. The purpose of my implementation is that I want to encrypt the data in a database.

有关密钥生成我用下面的构造函数这需要一个char []密码:

For key generation I use the following constructor which takes a char[] password:

public Cryptography(char[] password) throws NoSuchAlgorithmException,
        InvalidKeySpecException, NoSuchPaddingException {

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC");
    KeySpec spec = new PBEKeySpec(password, salt, 1024, 256);
    secretKey = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
    cipher = Cipher.getInstance(AES/CBC/PKCS5Padding);
}

所以,当我开始我的活动在我的Andr​​oid初始化我加密类的新实例,因此获得了生成的密钥。该盐是16字节的固定的随机字节[]。这样就意味着我总是得到相同的密钥。其原因更高版本。

So when I start my Activity in Android I initialize a new instance of my Cryptography class and therefore get a generated key. The salt is a fixed random byte[] of 16 bytes. So that means that I always get the same key. The reason for that later.

现在我在一个活动得到了一个对象后,我可以使用下面的加密和解密的方法总是相同的密钥:

Now after I got an object in one Activity I can use the following encrypt and decrypt methods with always the same key:

public byte[] encrypt(String cleartext) throws InvalidKeyException,
        IllegalBlockSizeException, BadPaddingException,
        UnsupportedEncodingException, InvalidParameterSpecException {

    cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    byte[] encText = cipher.doFinal(cleartext.getBytes(CHARSET_NAME));
    byte[] iv = cipher.getParameters()
            .getParameterSpec(IvParameterSpec.class).getIV();

    byte[] enc = new byte[IV_SIZE + encText.length];

    for (int i = 0; i < enc.length; i++) {
        if (i < IV_SIZE)
            enc[i] = iv[i];
        else if (i < enc.length)
            enc[i] = encText[i - IV_SIZE];
    }

    return enc;
}

public String decrypt(byte[] encryptedText) throws InvalidKeyException,
        InvalidAlgorithmParameterException, UnsupportedEncodingException,
        IllegalBlockSizeException, BadPaddingException {

    byte[] iv = new byte[IV_SIZE];
    byte[] dec = new byte[encryptedText.length - IV_SIZE];

    for (int i = 0; i < encryptedText.length; i++) {
        if (i < IV_SIZE)
            iv[i] = encryptedText[i];
        else if (i < encryptedText.length)
            dec[i - IV_SIZE] = encryptedText[i];
    }

    cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));

    return new String(cipher.doFinal(dec), CHARSET_NAME);
}

正如你所看到的,我救一个全新的IV的密文每次我加密消息一起。

As you can see, I save a fresh new IV along with the ciphertext everytime I encrypt a message.

在结论:我用一个加密密钥,这是随机盐和数据库表中每个字段一个新的IV

In conclusion: I use ONE encryption key, ONE random salt and a new IV for EVERY field in a database table.

首先,我想生成一个新的盐一个新的密钥和一个新的IV每次我在数据库表加密一个领域,并与一起保存所需的盐和IV的密文,或者至少一个表行。但是,我之所以这样做是像上面提到的,因为产生的Andr​​oid设备上的按键花费很多时间。我测试在模拟器上,但花了大约两秒钟生成密钥。这就是为什么我刚刚生成时活动开始一个密钥。

First I wanted to generate a new key with a new salt and a new IV everytime I encrypt ONE field in the database table and save the required salt and IV with along with the ciphertext, or at least for one table row. But the reason why I did it like above mentioned is, because generating a key on an Android device takes to much time. I tested in on an emulator, but it took about two seconds for generating a key. This is why I just generated one key when an Activity is started.

所以最后我的问题:
用我的方法,它是只用一个键足够安全,但新鲜的随机IV的每一个消息?目前,我没有看到另一种方式,使之尽可能的安全与性能保持它的平衡。

So finally my question: With my approach, is it secure enough by using just one key, but fresh random IV's for every message? Currently, I don't see another way to make it as secure as possible by keeping it in balance with performance.

我希望这是很清楚我写的,有人可以给我一些建议。

I hope it is clear enough what I wrote and somebody could give me some advice on that.

亲切的问候

xoidberg

推荐答案

我相信这个问题是不相关的,你(xoidberg),但也可能是相关的其他一些人。

I believe the question is not relevant for you (xoidberg), but it might be relevant for some other people.

从我所理解的 - 使用盐来创建密码(安全随机)键。如果每个用户都有一个随机的(不同的)盐 - 这是确定。否则可能会出现问题。

From what I understand - you use the salt to create a (securely random) key from password. If every user has a random (different) salt - it is ok. Otherwise it might be problematic.

我相信这是你做了什么,这样看来(我)是ok了。

I believe that this is what you did, so it seems (to me) to be ok.

我只是想提一提,通常要使用盐,当你节省一些值(如密码)的哈希函数。像MD5或SHA的Hash函数没有密钥,则必须为此增加随机性。这就是为什么你需要的盐,这也是为什么在这种情况下,你通常需要随机盐为每个值(如果你只是保存密码哈希有相同的盐,可以检测最常见的哈希值,并了解该用户的密码最常见的散列是123456)。在你的情况 - 每个用户都需要一个独特的盐

I just want to mention that usually you want to use salts when you save hash function of some values (usually password). Hash functions like MD5 or the SHAs do not have a key, and you must add randomness for this purpose. This is why you need the salt, and this is why in this case you usually need random salt for each value (if you just save passwords hashes with the same salt, one can detect the most common hashes and learn that the password of the users with the most common hash is 123456). In your case - every user needs a unique salt.

关于IV - 你真的需要一个随机每次(所以没关系)

About the IV - you really need a random one each time (so it's ok).

这篇关于Android的AES密码加密基于使用的每封邮件的一个关键和随机IV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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