【问题标题】:Blowfish on android studio for encryption/decryptionandroid studio 上的 Blowfish 用于加密/解密
【发布时间】:2016-12-29 19:47:36
【问题描述】:

我已经在这里搜索了几乎所有关于这个主题的主题,但我仍然无法弄清楚哪里出了问题。我在我的 android 应用程序上创建了 3 个EditTextEditText 插入密钥/密码以加密和解密的位置; EditText2 显示加密文本的地方; EditText3 显示解密文本的位置。

由于它仍然是一个早期测试,我已将消息或字符串作为应用程序中的变量放入 Crypt。

问题是加密给出了类似河豚算法的东西,所以没有问题(它以 2 == 结尾,所以我认为它工作正常)。我还尝试在解密之前对字符串进行解码,或者使用加密中的原始byte[],但没有任何好的结果。解密不会返回原始字符串文本,而是提供比加密文本更大的内容。我对河豚模式没有偏好,所以我从 Blowfish/CFB/NoPadding 开始。

str_keystr2str3 暂时被宣布为公开。 str2 将为EditText2 字段设置文本,str3 将为EditText3 字段设置文本。 输出示例: Example of output generated from the app

代码如下:

public void encrypt(){
    //encrypt
    EditText mEdit = (EditText)findViewById(R.id.editText);
    str_key = (String) mEdit.getText().toString();

    int iterationCount = 1000;
    int keyLength = 256;
    int saltLength = keyLength / 8; 

    SecureRandom random = new SecureRandom();
    byte[] salt = new byte[saltLength];
    random.nextBytes(salt);
    KeySpec keySpec = new PBEKeySpec(str_key.toCharArray(), salt,
            iterationCount, keyLength);
    SecretKeyFactory keyFactory = null;
    try {
        keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    byte[] keyBytes = new byte[0];
    try {
        keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
    } catch (InvalidKeySpecException e) {
        e.printStackTrace();
    }
    SecretKey key = new SecretKeySpec(keyBytes, "Blowfish");

    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding"); 
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        e.printStackTrace();
    }
    if ( cipher == null || key == null) {
        //throw new Exception("Invalid key or cypher");
        str2="error";
    }
    else {
        byte[] iv = new byte[cipher.getBlockSize()];
        random.nextBytes(iv);
        IvParameterSpec ivParams = new IvParameterSpec(iv);
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key,ivParams);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }


        try {
            raw = cipher.doFinal(message.getBytes("UTF-8"));
        } catch (IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        str2 = Base64.encodeToString(raw,Base64.DEFAULT);

    }


}

这里是解密函数:

    public void decrypt(){
          int iterationCount = 1000;
          int keyLength = 256;
          int saltLength = keyLength / 8; 
          SecureRandom random = new SecureRandom();
          byte[] salt = new byte[saltLength];
          random.nextBytes(salt);
          KeySpec keySpec = new PBEKeySpec(str_key.toCharArray(), salt,  iterationCount, keyLength);
          SecretKeyFactory  keyFactory = null;
          try {
               keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
              } catch (NoSuchAlgorithmException e) {
                 e.printStackTrace();
              }
              byte[] keyBytes = new byte[0];
              try {
                keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
                } catch (InvalidKeySpecException e) {
                  e.printStackTrace();
                }
              SecretKey key = new SecretKeySpec(keyBytes, "Blowfish");



    Cipher cipher2 = null;
    try {
        cipher2 = Cipher.getInstance("Blowfish/CBC/PKCS5Padding"); 
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        e.printStackTrace();
    }
    iv = new byte[cipher2.getBlockSize()];
    random.nextBytes(iv);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    try {
        cipher2.init(Cipher.DECRYPT_MODE, key, ivSpec );
    } catch (InvalidKeyException  | InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }
    byte[] decryptedBytes = null;
    byte[] app= Base64.decode(str2,Base64.DEFAULT);

    try {
        decryptedBytes = cipher2.doFinal(app);
    } catch (IllegalBlockSizeException | BadPaddingException  e) {
        e.printStackTrace();
    }


    str3 = Base64.encodeToString(decryptedBytes,Base64.DEFAULT);
}

【问题讨论】:

    标签: java android encryption blowfish


    【解决方案1】:

    您将加密结果编码为 base64,但是当您解密时,您会获取该 base64 的纯字节。您应该首先进行 base64 解码以获取密文的实际字节数组,然后对其进行解密。

    您还直接从 UTF8 字节数组派生密钥,这是一种非常糟糕的方法。您应该改用 KDF。 PBKDF2 是这里最常用的。

    生成 IV 的方式(根本不生成)也很糟糕。它应该随机生成并添加到密文中。它不需要保密,只是不可预测。

    最后,您根本不使用 HMAC,因此任何人都可以更改密文而您不会知道。

    【讨论】:

    • 感谢您的回答。我也尝试使用 base64 解码,并且使用原始的“pre”编码字节数组进行解密,但没有结果。你能举例说明我应该做什么吗?我应该只用 KDF.PBKDF2 更改 UTF-8 吗?我还尝试将 IV 生成为: IvParameterSpec ivSpec = new IvParameterSpec(keySpec.getEncoded()); //在解密函数中;但我得到运行时错误。你也能给我举个例子吗?
    • 如何使用 HMAC 来避免更改密文?
    • 这都是你可以google搜索的东西,如果我只是为你写代码你不会学到任何东西!如果你尝试解码base64,那么你只是做错了什么。尝试将原始帖子中的代码编辑为您尝试过的内容,我会从那里帮助您。
    • 我并不是在寻找一个简单的出路。我会调查你提到的东西,我一如既往地感谢你的回答。我很沮丧,因为过去 22 天我一直在这里和谷歌上搜索,得到的代码比我必须用于 android studio 的代码简单得多,几乎没有人必须专门使用 IV 参数声称他们的代码“有效” .我还添加了我在解密函数中使用的解码测试,结果我得到了不同的 Blowfish 加密代码。
    • 我还添加了 PBKDF2 密钥派生,这也有助于生成用于加密的 IV 参数。将实例更改为 Blowfish/CBC/PKCS5Padding。现在好点了吗?我也会尝试更改解密,看看会发生什么。
    猜你喜欢
    • 2015-09-25
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2016-07-25
    • 2019-05-15
    相关资源
    最近更新 更多