Android的AES 256位加密数据 [英] Android AES 256-bit Encrypt data

查看:556
本文介绍了Android的AES 256位加密数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我已经看到了很多例子,做了很多谷歌上搜索的,看着就堆栈溢出的例子...我需要帮助。我有一个Android应用程序,我存储的用户名和密码的设备上,我需要进行加密AES 256从看的例子,这是我到目前为止有:

So I've seen a lot of examples, and done a lot of googling, and looked at examples on Stack Overflow... and I need help. I've got an Android application and I'm storing username and passwords on the device, and I need to encrypt them AES 256. From looking at examples, this is what I have so far:

public class Security {
Cipher ecipher;
Cipher dcipher;

// 8-byte Salt
byte[] salt = {
        (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
        (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
};

// Iteration count
int iterationCount = 19;

public Security (String passPhrase) {
    try {
        // Create the key
        KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
        SecretKey key = SecretKeyFactory.getInstance(
                "PBEWithSHAAndAES").generateSecret(keySpec);
        ecipher = Cipher.getInstance(key.getAlgorithm());
        dcipher = Cipher.getInstance(key.getAlgorithm());

        // Prepare the parameter to the ciphers
        AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

        // Create the ciphers
        ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
    } catch (Exception e) { e.printStackTrace(); }
}

public String encrypt(String str) {
    try {
        // Encode the string into bytes using utf-8
        byte[] utf8 = str.getBytes("UTF8");

        // Encrypt
        byte[] enc = ecipher.doFinal(utf8);

        // Encode bytes to base64 to get a string
        return Base64.encodeToString(enc, Base64.DEFAULT);
    } catch (Exception e) { 
        e.printStackTrace();
        return null;
    }
}

public String decrypt(String str) {
    try {
        // Decode base64 to get bytes
        byte[] dec = Base64.decode(str, Base64.DEFAULT);

        // Decrypt
        byte[] utf8 = dcipher.doFinal(dec);

        // Decode using utf-8
        return new String(utf8, "UTF8");
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
}

我想它基于密码进行,因此用户将创建一个账户在第一时间使用到及时通知服务器所需的用户名和密码,并创建将被用作键这些凭据PIN存储在数据库中。

I'm trying to make it password based, so a user will create an account the first time using the username and password needed to communicate back to the server, and create a PIN that will be used as the key for these credentials stored in the database.

什么我主要关心的是这看起来安全吗?我知道一个固定的盐是坏的,我怎么解决这个问题?

What I'm mainly concerned about is does this look secure? I know a fixed salt is bad, how do I fix that?

我知道有没有像这个一个十亿的问题,但我希望有人刚出来,并说这是安全或这是不安全的,改变这种

I know there's been like a billion questions about this, but I want someone to just come out and say "THIS IS SECURE" or "THIS IS NOT SECURE, CHANGE THIS"

谢谢!

编辑:

所以这是code我到目前为止,这似乎是工作...     公共类安全{

So this is the code I have so far, and it seems to be working... public class Security {

Cipher ecipher;
Cipher dcipher;
byte[] salt = new byte[8];
int iterationCount = 200;

 public Security (String passPhrase) {
    try {
        // generate a random salt
        SecureRandom random = new SecureRandom();
        random.nextBytes(salt);

        // Create the key
        KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
        SecretKey key = SecretKeyFactory.getInstance(
                "PBEWithSHA256And256BitAES-CBC-BC").generateSecret(keySpec);
        ecipher = Cipher.getInstance(key.getAlgorithm());
        dcipher = Cipher.getInstance(key.getAlgorithm());

        // Prepare the parameter to the ciphers
        AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

        // Create the ciphers
        ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
    } catch (Exception e) { e.printStackTrace(); }
}

public String encrypt(String str) {
    try {
        // Encode the string into bytes using utf-8
        byte[] utf8 = str.getBytes("UTF8");

        // Encrypt
        byte[] enc = ecipher.doFinal(utf8);

        // Encode bytes to base64 to get a string
        return Base64.encodeToString(enc, Base64.DEFAULT);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

public String decrypt(String str) {
    try {
        // Decode base64 to get bytes
        byte[] dec = Base64.decode(str, Base64.DEFAULT);

        // Decrypt
        byte[] utf8 = dcipher.doFinal(dec);

        // Decode using utf-8
        return new String(utf8, "UTF8");
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

public int getIterationCount() {
    return iterationCount;
}

public String getSalt() {
    return Base64.encodeToString(salt, Base64.DEFAULT);
}
}

我用这个code来测试它:

I used this code to test it:

 Security s = new Security(pinBox.getText().toString());
            String encrypted = s.encrypt(passwordBox.getText().toString());
            String decrypted = s.decrypt(encrypted);
            builder.setMessage("pin: " + pinBox.getText().toString() + "\n" +
                    "password: " + passwordBox.getText().toString() + "\n" +
                    "encrypted: " + encrypted + "\n" +
                    "decrypted: " + decrypted + "\n" +
                    "salt: " + s.getSalt());

所以,我并不需要担心的初始化向量?或C表示的密码算法具体硬$ C $?

So I don't need to worry about an initialization vector? Or specifically hardcode a Cipher algorithm?

再次感谢!

推荐答案

编辑:虽然$ C $低于C是正确的,你有什么是做基本上是同样的事情,从密码衍生出的IV,所以你不要'T必须单独存放。

While the code below is correct, what you have is doing basically the same thing, with the IV derived from the password, so you don't have to store it separately.

贵code按预期方式工作?对于实际的加密/解密你想在CBC模式使用AES,最有可能。那么你就需要一个第四,所以它变成是这样的:

Does your code work as expected? For the actual encryption/decryption you would want to use AES, most probably in CBC mode. Then you would need an IV, so it becomes something like this:

ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[IV_LENGTH];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] enc = ecipher.doFinal(utf8);

无论是安全取决于你使用的是本作。盐的目的是为了使其难以暴力破解密码:如果它是随机的,攻击者不能使用pre-密码生成的表格(密码短语>键)。如果你不是太担心这种攻击,你可以把它固定。如果您决定让它随机的,只是将其存储的加密数据。同样具有四。

Whether it is secure depends on what you are using this for. The purpose of the salt is to make it harder to brute force the passphrase: if it's random the attacker cannot use pre-generated passphrase tables (passphrase->key). If you are not too worried about this sort of attack, you might leave it fixed. If you decide to make it random, just store it with the encrypted data. Same with the IV.

这篇关于Android的AES 256位加密数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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