【问题标题】:password encrytion.decryption in androidandroid中的密码加密解密
【发布时间】:2014-04-20 13:33:23
【问题描述】:
String text = name1.getText().toString();
    // Sending side
    byte[] data = null;
    try {
        data = text.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e1) {
    e1.printStackTrace();
    }
    String base64 = Base64.encodeToString(data, Base64.DEFAULT);

能够加密密码并愿意解密相同的密码,但我有一些想法,我不确定这是我第一次尝试加密密码。以这种方式加密密码是否安全,因为我尝试加密密码:zxc,结果只是一个四个字母的密码(其结果是:enhj)所以我想知道这是否是加密密码的安全方法.有关如何重新制作代码以使其更安全且不易解码的任何想法以及如何解密加密密码的想法?

更新:这是我在this site here 找到的加密和解密示例,但我无法让它运行。

加密

String password  = "password";
int iterationCount = 1000;
int keyLength = 256;
int saltLength = keyLength / 8; // same size as key output

SecureRandom random = new SecureRandom();
byte[] salt = new byte[saltLength];
randomb.nextBytes(salt);
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt,
                    iterationCount, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory
                    .getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize());
random.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
byte[] ciphertext = cipher.doFinal(plaintext.getBytes("UTF-8"));

解密

String[] fields = ciphertext.split("]");
byte[] salt = fromBase64(fields[0]);
byte[] iv = fromBase64(fields[1]);
byte[] cipherBytes = fromBase64(fields[2]);
// as above
SecretKey key = deriveKeyPbkdf2(salt, password);

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivParams);
byte[] plaintext = cipher.doFinal(cipherBytes);
String plainrStr = new String(plaintext , "UTF-8");

【问题讨论】:

    标签: android encryption passwords cryptography


    【解决方案1】:

    你已经标记了这个密码学、密码和加密,所以我会这样回答。

    首先,Base64 实际上并不是加密,它只是编码 - 本质上是从 8 位字节变为 6 位字节,您的测试非常完美 - 3*8 位字符 = 24 位。 24 位/6 位 = 4 个 Base64 字符。我还验证了 enhj 确实是 my own C implementation of Base64 上 zxc 的 Base64 编码。要进一步证明这一点,请注意您没有提供任何加密密钥!

    其次,对于用户身份验证(我假设您正在这样做),不要加密密码 - 这是一个主要的 blunder Adobe just made。对于用户身份验证,您无需再次查看用户密码 - 您只需验证他们输入的内容是否与之前相同。因此,当他们第一次输入密码时,您可以对其进行加盐和哈希处理。下次,您检索第一次使用的盐,并使用相同的盐(和迭代次数/工作因子)对新输入的密码进行散列 - 如果结果与您记录的结果相同,请让它们进入,因为输入相同的密码会得到相同的结果。

    How to securely hash passwords? 的三个规范答案是 PBKDF2、Bcrypt 和 Scrypt。出现了关于 Android 密码哈希的快速 Google 搜索:

    在所有情况下,选择尽可能高的迭代次数/工作因子(在您可以遵守许可的情况下为您选择的算法使用尽可能快的库)。您的 salt 应该是 8 到 16 字节长度范围内的加密随机字节序列。

    特别是对于 PBKDF2,永远不要使用比本机哈希大小更多的 outputBytes,否则会给攻击者一个比较优势 - SHA-1 的本机大小是 20 字节,SHA-256 是 32 字节,SHA-512 是 64 字节.

    如果您确实需要加密而不是身份验证,那么上面的“使用密码术安全地存储凭据”链接也涵盖了这一点,尽管更好的答案是存储盐和迭代次数/工作因素,并简单地从每次都输入密码-如果数据解密,那就太好了。如果不是,那么,密码错误。

    【讨论】:

    • 哇,你写了这么多。你值得 +1
    • 我将进一步研究您的答案,以便我可以在我的程序中实施它您对身份验证的看法是正确的,我认为最好加密密码,我什至没有意识到这不是一个加密我刚刚在谷歌上搜索它,它给了我这个结果,所以我在我的示例项目上尝试了它。无论如何,我会给你一个 +1,因为你向我展示了正确的事情。我希望我能让它工作,我会回来找你的,因为我仍然不知道盐和你在答案中所说的事情
    • 至少阅读Thomas Porrin's answer to How to Securely Hash Passwords - 这是一本非常好的入门书。
    • 如果您想问一下,您建议我在我的示例应用程序中对注册用户的密码进行哈希处理,或者只使用我找到的密码,然后当用户使用时对密码进行编码登录或更改密码我将再次对输入的密码进行编码并将密码与我的数据库中的密码进行比较以验证密码是否相同
    • 在更改密码/密码设置时 1) 生成一个 8-16 字节的随机盐,2) 使用 PBKDF2-HMAC-SHA-256 或 PBKDF2-HMAC-SHA-1 或 BCrypt 以及尽可能多的散列迭代/工作因素,你可以花时间,3)存储用户名(明文),盐(明文)和迭代/工作因素和结果哈希。可选:Base64 存储前的结果。当用户想要使用现有密码登录时,1) 检索该用户名的盐和迭代/工作因子,2) 使用相同的盐和迭代/工作因子对输入的任何内容进行哈希处理,3) 与 has 进行比较。进阶:固定时间比较。
    【解决方案2】:

    你没有加密任何东西。您正在将字节转换为 base64 编码。您需要使用加密算法。见http://examples.javacodegeeks.com/core-java/security/simple-symmetric-key-encrypt-decrypt/

    【讨论】:

    • 我无法检查这个,但我认为你与之前的答案有相同的想法,所以 +1 给你的队友 :)
    猜你喜欢
    • 2014-10-17
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多