简体   繁体   中英

Why am I not getting the output in the string format?

In the following snippet I try to print encrypted array in a simple string format.

        KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
        SecretKey secretKey = keyGenerator.generateKey();
        Cipher cipher = Cipher.getInstance("Blowfish"); 
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        String input = "password";
        byte encrypted[] = cipher.doFinal(input.getBytes());
        String s = new String(encrypted);
        System.out.println(s);

But what I get is `┐╫Y²▓ô┴Vh¬∙:╪⌡¶ . Why is it ? How can I print it in the proper string format ?

Encode the bytes in Base64 encoding ( How do I convert a byte array to Base64 in Java? )

Or Hex: How to convert a byte array to a hex string in Java?

System.out.println( Hex.encodeHexString( bytes ) );

You could use Base64 encoding from common-codec .

    KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
    SecretKey secretKey = keyGenerator.generateKey();
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);
    String input = "password";
    byte encrypted[] = cipher.doFinal(input.getBytes());
    System.out.println(new String(Base64.encodeBase64(encrypted)));

Output:

8KA8ahr6INnY4qqtzjAJ8Q==

Most cryptographic algorithms (including blowfish) deal with binary data meaning that it will take binary data in and split out binary data that has been transformed by the algorithm (with the provided specs).

Binary data, as you know is != to string data, however binary data can be represented as string data (using hex, base64, etc).

If we look at your example code we can see this line:

byte encrypted[] = cipher.doFinal(input.getBytes());

This is what it is doing step by step:

  1. It first converts string data into a binary data equivalent using the platform's default charset (NOT RECOMMENDED, but irrelevant).

  2. It is passing the binary data (in form of a byte array) to the method doFinal().

  3. The doFinal() method is processing this byte array via the specifications specified in the statements prior to this line (Blowfish, encryption).

  4. The doFinal() statement is returning a byte array which represents the processed (encrypted, in your case) data.

The fact that the data originally came from a string is no longer relevant because of the nature of the encryption operation does not account for the source or type of the data. The encrypted byte array now contains data that may not be valid charset encoded string. Trying to use a character set to decode the string would most likely result in garbage output as the binary data is no longer a valid string.

However, binary data can be represented directly by outputting the VALUE of the actual bytes rather than what the charset equivalent mapping is (eg A byte may have the value of 97, which represented in hex is: 0x61 but decoded via ASCII results in the character 'a').

Consider this code to output your encrypted data in hex:

KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
SecretKey secretKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("Blowfish"); 
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
String input = "password";
byte encrypted[] = cipher.doFinal(input.getBytes());

StringBuilder str = new StringBuilder();

for(byte b:encrypted){
     str.append(String.format("%02x", b));
}

String encData = str.toString();
System.out.println(encData);

PS: Don't use getBytes() without any arguments! Supply your own charset like UTF-8. Do as follows:

byte encrypted[] = cipher.doFinal(input.getBytes(Charset.forName("UTF-8")));

您可以尝试:

new String(bytes, StandardCharsets.UTF_8)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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