简体   繁体   English

Android Studio上的河豚进行加密/解密

[英]Blowfish on android studio for encryption/decryption

I've searched almost all topics here about this subject but I still can't figure out what's wrong. 我在这里搜索了几乎所有与此主题相关的主题,但仍然无法弄清问题所在。 I've created 3 EditText on my android app: EditText where you insert the key/password to encrypt and decrypt; 我已经在Android应用程序上创建了3个EditTextEditText ,您在其中插入密钥/密码进行加密和解密; EditText2 where it is shown the encrypted text; EditText2中显示加密文本; EditText3 where it is shown the decrypted text. EditText3显示解密后的文本。

Since it's still an early test, I've put the message or string to Crypt as variable in the app. 由于这仍是早期测试,因此我已将消息或字符串作为变量放入应用程序中的Crypt中。

The Problem is that the encryption give something like a blowfish algorithm, so no problem there (it end with 2 == so I think it's working right). 问题是加密提供了类似河豚算法的东西,所以那里没有问题(它以2 ==结尾,所以我认为它工作正常)。 I've also tried to decode the string before the decryption or using the raw byte[] from encryption without any good result. 我也曾尝试在解密之前对字符串进行解码,或者使用加密中的raw byte[]却没有任何好的结果。 The decryption doesn't give back the original String text, instead give something bigger than the encrypted text. 解密不会返回原始的String文本,而是提供比加密文本更大的内容。 I don't have a preference on the mode of blowfish so I started easy as Blowfish/CFB/NoPadding. 我对河豚的模式没有偏爱,所以我开始做河豚/ CFB / NoPadding很容易。

str_key , str2 and str3 are declared public for now. str_keystr2str3声明为公共。 str2 will set the text for EditText2 field and str3 will set the text for EditText3 field. str2将设置文本EditText2场和str3将设置文本EditText3领域。 An example of output: Example of output generated from the app 输出示例应用程序生成的输出示例

Here's the code : 这是代码:

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);

    }


}

Here is the decrypt function: 这是解密功能:

    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);
}

You encode the encrypted result to base64 but then when you decrypt, you take the plain bytes of that base64. 您可以将加密结果编码为base64,但是当您解密时,将使用该base64的纯字节。 You should instead base64 decode first to get the actual byte array of ciphertext and then decrypt that. 相反,您应该先进行base64解码,以获取密文的实际字节数组,然后再对其进行解密。

You are also deriving your key directly from the UTF8 byte array, which is a very poor way to do so. 您还直接从UTF8字节数组派生密钥,这是一种非常差的方法。 You should instead use a KDF. 您应该改用KDF。 PBKDF2 is the most commonly used here. PBKDF2是此处最常用的。

The way you generate an IV (by not generating one at all) is very poor also. 生成IV(完全不生成IV)的方式也很差。 It should be randomly generated and prepended to the ciphertext. 它应该是随机生成的,并以密文开头。 It doesn't need to be secret, just unpredictable. 它不需要是秘密的,只是不可预测的。

Lastly, you don't use a HMAC at all, so anyone could change the ciphertext and you wouldn't know. 最后,您根本不使用HMAC,因此任何人都可以更改密文,并且您不会知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM