Decrypting in Java with Blowfish

a 夏天 提交于 2019-12-03 14:10:38

问题


Hullo,

I am encrypting and decrypting in Java with Blowfish.

The encryption works fine, but the decryption fails.

Here is my Java code for decrypting :

String encryptedString = … ;
String decryptedString = null;
SecretKeySpec key = new SecretKeySpec(myKey.getBytes(), "Blowfish");
Cipher cipher;
try {
    cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] decrypted = cipher.doFinal(encryptedString.getBytes());
    decryptedString = new String(decrypted, Charset.forName("UTF-8"));
} [ catch Exceptions … ]

I get an exception :

Exception. javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

Can you tell me how to make this simply work ? Thank you.

The input I give comes from my encryption Java code, + encoding in Base64, and I decode it from Base64 just before giving it to this decrypting operation.


回答1:


Converting bytes to hex and back is tricky. This should solve your problem. (You need to fix your string representation of encryptedString)

Output:

StackOverflow 537461636B4F766572666C6F77 [83, 116, 97, 99, 107, 79, 118, 101, 114, 102, 108, 111, 119]
J~3¹ÙÂÖ"¢ª„¨u 194A7E33B9060CD9C2D622A2AA84A875 [25, 74, 126, 51, -71, 6, 12, -39, -62, -42, 34, -94, -86, -124, -88, 117]
StackOverflow 537461636B4F766572666C6F77 [83, 116, 97, 99, 107, 79, 118, 101, 114, 102, 108, 111, 119]

Code:

import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class Main {

  public static void main(String[] args) throws Exception {

    KeyGenerator keygenerator = KeyGenerator.getInstance("Blowfish");
    SecretKey secretkey = keygenerator.generateKey();

    String plaintextString = "StackOverflow";
    System.out.println(plaintextString + " " + bytesToHex(plaintextString.getBytes()) + " " + Arrays.toString(plaintextString.getBytes()));

    SecretKeySpec key = new SecretKeySpec(secretkey.getEncoded(), "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");

    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] encrypted = cipher.doFinal(plaintextString.getBytes());
    String encryptedString = bytesToHex(encrypted);
    System.out.println(new String(encrypted) + " " + encryptedString + " " + Arrays.toString(encrypted));

    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] decrypted = cipher.doFinal(hexToBytes(encryptedString));
    String decryptedString = bytesToHex(decrypted);
    System.out.println(new String(decrypted) + " " + decryptedString + " " + Arrays.toString(decrypted));

  }

  public static byte[] hexToBytes(String str) {
    if (str == null) {
      return null;
    } else if (str.length() < 2) {
      return null;
    } else {
      int len = str.length() / 2;
      byte[] buffer = new byte[len];
      for (int i = 0; i < len; i++) {
        buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
      }
      return buffer;
    }

  }

  public static String bytesToHex(byte[] data) {
    if (data == null) {
      return null;
    } else {
      int len = data.length;
      String str = "";
      for (int i = 0; i < len; i++) {
        if ((data[i] & 0xFF) < 16)
          str = str + "0" + java.lang.Integer.toHexString(data[i] & 0xFF);
        else
          str = str + java.lang.Integer.toHexString(data[i] & 0xFF);
      }
      return str.toUpperCase();
    }
  }
}



回答2:


Your myKey variable lenght must be multiple of 8




回答3:


String encryptedString = … ;  
String decryptedString = null;
SecretKeySpec key = new SecretKeySpec(myKey.getBytes(), "Blowfish");
private static byte[] linebreak = {}; // Remove Base64 encoder default linebreak
private static Base64 coder;
Cipher cipher;
try {
    coder = new Base64(32, linebreak, true);
    cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] decrypted = cipher.doFinal(encryptedString.getBytes());
    decryptedString = new String(coder.encode(decrypted));
} [ catch Exceptions … ]

You can use Base64 class to solve this problem.




回答4:


Now I have the solution !

First, there were some problems with Unicode, so I have put ISO-8859-1 everywhere. Including in the Base64 encoding and decoding.

Then, I have juggled with the variants.

Here is my Java code which works for Blowfish decryption :

String encryptedString = … ;
String decryptedString = null;
SecretKeySpec key = new SecretKeySpec(myKey.getBytes(CHARSET_ISO_8859_1), "Blowfish");
Cipher cipher;
try {
    cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] decrypted = cipher.doFinal(encryptedString.getBytes(CHARSET_ISO_8859_1));
    decryptedString = new String(decrypted, CHARSET_ISO_8859_1);
} [ catch Exceptions … ]

Note that I have replaced "Blowfish" with "Blowfish/ECB/PKCS5Padding" for getting the Cipher instance, but, if you do the same for the key, it fails.

The key myKey has to be a Latin-1 string of 8 characters. This makes a key of 128 bits. The Blowfish algorithm allows bigger keys, but they fail in Java because of the USA export restriction in the JRE — the USA allow encryption but not stronger than what the NSA can break.

The CHARSET_ISO_8859_1 is a constant defined like this :

final Charset CHARSET_ISO_8859_1 = Charset.forName("ISO-8859-1");

And Charset is java.nio.charset.Charset.

Last but not least, I have changed my encryption Java code accordingly.




回答5:


You should definitely be more explicit with the Cipher by declaring the mode and padding. How is this code getting encrypted? What is actually in the String encryptedString? Is it hex encoded or base64 encoded? If it isn't encoded that could definitely be a source of trouble.




回答6:


Try this

private byte[] encrypt(String key, String plainText) throws GeneralSecurityException {

    SecretKey secret_key = new SecretKeySpec(key.getBytes(), ALGORITM);

    Cipher cipher = Cipher.getInstance(ALGORITM);
    cipher.init(Cipher.ENCRYPT_MODE, secret_key);

    return cipher.doFinal(plainText.getBytes());
}

here you can find whole class with enc/dec --- http://dexxtr.com/post/57145943236/blowfish-encrypt-and-decrypt-in-java-android



来源:https://stackoverflow.com/questions/15948662/decrypting-in-java-with-blowfish

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!