Android AES基于密码的加密,每封邮件使用一个密钥和随机IV

Android AES基于密码的加密,每封邮件使用一个密钥和随机IV,android,security,aes,password-protection,encryption-symmetric,Android,Security,Aes,Password Protection,Encryption Symmetric,受这篇文章的启发,我目前正在Android上使用AES 256实现对称加密/解密: . 我实现的目的是要加密数据库中的数据 对于密钥生成,我使用以下构造函数,它接受char[]密码: public Cryptography(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException { SecretKeyFactory factory

受这篇文章的启发,我目前正在Android上使用AES 256实现对称加密/解密: . 我实现的目的是要加密数据库中的数据

对于密钥生成,我使用以下构造函数,它接受char[]密码:

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);
}
因此,当我在Android中启动我的活动时,我初始化了我的加密类的一个新实例,因此得到了一个生成的密钥。salt是一个16字节的固定随机字节[]。这意味着我总是得到相同的钥匙。原因是后来

现在,在一个活动中获得一个对象后,我可以使用以下始终相同密钥的加密和解密方法:

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);
}
public byte[]encrypt(字符串明文)引发InvalidKeyException,
IllegalBlockSizeException,BadPaddingException,
UnsupportedEncodingException,InvalidParameterSpecException{
cipher.init(cipher.ENCRYPT_模式,secretKey);
byte[]encText=cipher.doFinal(cleartext.getBytes(CHARSET_NAME));
字节[]iv=cipher.getParameters()
.getParameterSpec(IvParameterSpec.class).getIV();
byte[]enc=新字节[IV_SIZE+encText.length];
对于(int i=0;i
正如您所看到的,每次加密邮件时,我都会保存一个新的IV和密文

总之:我对数据库表中的每个字段使用一个加密密钥、一个随机salt和一个新的IV

首先,每当我加密数据库表中的一个字段并将所需的salt和IV与密文一起保存时,或者至少为一个表行保存时,我希望生成一个带有新salt和新IV的新密钥。但我这样做的原因是,在Android设备上生成一个密钥需要很多时间。我在一个模拟器上进行了测试,但生成一个密钥大约需要两秒钟。这就是为什么我在活动启动时只生成了一个键

最后,我的问题是: 就我的方法而言,仅仅使用一个密钥,但每个消息都使用新的随机IV,这是否足够安全?目前,我看不到通过保持性能平衡来尽可能保证安全性的其他方法

我希望我写的东西足够清楚,有人可以给我一些建议

问候


我相信这个问题与你无关,但可能与其他人有关

据我所知,您使用salt从密码创建(安全随机)密钥。如果每个用户都有一个随机的(不同的)盐-这是可以的。否则可能会有问题

我相信这就是你所做的,所以(对我来说)似乎没问题

我只想提一下,通常在保存某些值(通常是密码)的哈希函数时,您希望使用salt。像MD5或SHA这样的散列函数没有密钥,因此必须添加随机性。这就是为什么您需要salt,这就是为什么在这种情况下,您通常需要为每个值使用随机salt(如果您仅使用相同的salt保存密码哈希,您可以检测最常见的哈希,并了解最常见哈希的用户的密码是123456)。在您的情况下,每个用户都需要一种独特的盐

关于静脉注射-你真的需要每次随机注射一次(所以没关系)