This question already has answers here:
Encoding as Base64 in Java
(19 answers)
Closed 7 years ago.
I want to encode a string into base64 and transfer it through a socket and decode it back.
But after decoding it gives different answer.
Following is my code and result is "77+9x6s="
import javax.xml.bind.DatatypeConverter;
public class f{
public static void main(String a[]){
String str = new String(DatatypeConverter.parseBase64Binary("user:123"));
String res = DatatypeConverter.printBase64Binary(str.getBytes());
System.out.println(res);
}
}
Any idea about how to implement this?
You can use following approach:
import org.apache.commons.codec.binary.Base64;
// Encode data on your side using BASE64
byte[] bytesEncoded = Base64.encodeBase64(str.getBytes());
System.out.println("encoded value is " + new String(bytesEncoded));
// Decode data on other side, by processing encoded data
byte[] valueDecoded = Base64.decodeBase64(bytesEncoded);
System.out.println("Decoded value is " + new String(valueDecoded));
Hope this answers your doubt.
Java 8 now supports BASE64 Encoding and Decoding. You can use the following classes:
java.util.Base64, java.util.Base64.Encoder and java.util.Base64.Decoder.
Example usage:
// encode with padding
String encoded = Base64.getEncoder().encodeToString(someByteArray);
// encode without padding
String encoded = Base64.getEncoder().withoutPadding().encodeToString(someByteArray);
// decode a String
byte [] barr = Base64.getDecoder().decode(encoded);
The accepted answer uses the Apache Commons package but this is how I did it using Java's native libraries
Java 11 and up
import java.util.Base64;
public class Base64Encoding {
public static void main(String[] args) {
Base64.Encoder enc = Base64.getEncoder();
Base64.Decoder dec = Base64.getDecoder();
String str = "77+9x6s=";
// encode data using BASE64
String encoded = enc.encodeToString(str.getBytes());
System.out.println("encoded value is \t" + encoded);
// Decode data
String decoded = new String(dec.decode(encoded));
System.out.println("decoded value is \t" + decoded);
System.out.println("original value is \t" + str);
}
}
Java 6 - 10
import java.io.UnsupportedEncodingException;
import javax.xml.bind.DatatypeConverter;
public class EncodeString64 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "77+9x6s=";
// encode data using BASE64
String encoded = DatatypeConverter.printBase64Binary(str.getBytes());
System.out.println("encoded value is \t" + encoded);
// Decode data
String decoded = new String(DatatypeConverter.parseBase64Binary(encoded));
System.out.println("decoded value is \t" + decoded);
System.out.println("original value is \t" + str);
}
}
The better way would be to try/catch the encoding/decoding steps but hopefully you get the idea.
For Spring Users , Spring Security has a Base64 class in the org.springframework.security.crypto.codec package that can also be used for encoding and decoding of Base64.
Ex.
public static String base64Encode(String token) {
byte[] encodedBytes = Base64.encode(token.getBytes());
return new String(encodedBytes, Charset.forName("UTF-8"));
}
public static String base64Decode(String token) {
byte[] decodedBytes = Base64.decode(token.getBytes());
return new String(decodedBytes, Charset.forName("UTF-8"));
}
The following is a good solution -
import android.util.Base64;
String converted = Base64.encodeToString(toConvert.toString().getBytes(), Base64.DEFAULT);
String stringFromBase = new String(Base64.decode(converted, Base64.DEFAULT));
That's it. A single line encoding and decoding.
import javax.xml.bind.DatatypeConverter;
public class f{
public static void main(String a[]){
String str = new String(DatatypeConverter.printBase64Binary(new String("user:123").getBytes()));
String res = DatatypeConverter.parseBase64Binary(str);
System.out.println(res);
}
}
Related
I have generated Base64 encoded value using below Scala code:
println(Base64.getEncoder.encodeToString("E5E9FA1BA31ECD1AE84F75CAAA474F3A".getBytes(StandardCharsets.UTF_8)))
YxRfXk827kPgkmMUX15PNg==
Now I am trying to convert "YxRfXk827kPgkmMUX15PNg==" to Hex. I tried with below Java code but no luck:
public static void main(String[] args) throws DecoderException {
String guid = "RTVFOUZBMUJBMzFFQ0QxQUU4NEY3NUNBQUE0NzRGM0E=";
byte[] hexString = Hex.decodeHex(guid);
System.out.println(hexString);
Exception in thread "main" org.apache.commons.codec.DecoderException: Illegal hexadecimal character R at index 0
When I explored I found below working Java code:
String guid = "YxRfXk827kPgkmMUX15PNg==";
byte[] decoded = Base64.decodeBase64(guid);
String hexString = Hex.encodeHexString(decoded);
System.out.println(hexString);
4535453946413142413331454344314145383446373543414141343734463341
But here Base64 values is getting decoded and then converted to Hex. I am trying to figure out if there is a way we can directly convert Base64 to Hex? Please excuse as it looks like a duplicate question and thanks in advance.
Since it is a String, it already has a way to get the ByteArray.
Don't decode the Base64, simply request the bytes from the String:
public static void main(String[] args) {
String guid = "YxRfXk827kPgkmMUX15PNg==";
String hexString = Hex.encodeHexString(guid.getBytes());
System.out.println(hexString);
}
This basically means you only have to convert your string to a Byte[].
You can see that the business logic code is very simple and that the original text and the hex encoded are the same by trying to decode them in a test:
// actual business logic
public String hexEncoder(String content) {
return Hex.encodeHexString(content.getBytes());
}
// input and assertion
#Test
public void hexEncoder() throws DecoderException {
String guid = "YxRfXk827kPgkmMUX15PNg==";
String hexString = hexEncoder(guid);
String hexDecoded = new String(Hex.decodeHex(hexString));
// no need to decode Base64 but might be useful for `printLn` or debugging
String s = new String(Base64.decodeBase64(guid));
String s1 = new String(Base64.decodeBase64(hexDecoded));
assertEquals(s, s1);
}
import org.junit.Test;
import java.util.Base64;
import org.junit.Assert.*;
import java.util.Random;
...
#Test
public void testEncoding(){
byte[] data = new byte[32];
new Random().nextBytes(data);
String base64 = Base64.getEncoder().encodeToString(data);
assertEquals(data, Base64.getDecoder().decode(base64));
}
#Test
public void testDecoding(){
String base64 = "ABCDEFGHIJKLRMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/A==";
byte[] data = Base64.getDecoder().decode(base64);
assertEquals(base64, Base64.getEncoder().encodeToString(data));
}
The testEncoding test fails with an AssertionError:
Expected :[B#6bf2d08e
Actual :[B#5eb5c224
And I can't see why.
The flaw is in then Assertion not in the code.
assertEquals will compare the address of the byte array in memory
assertArrayEquals will compare the content of the byte array
Try this. You should encode a normal String, and decode a normal String, not a byte-array:
#Test
public void verify() throws Exception {
String normalString = "ABCDEFGHIJKLRMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/A==";
byte[] asBytes = normalString.getBytes();
String encoded = Base64.getEncoder().encodeToString(asBytes);
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String decoded = new String(decodedBytes);
assertEquals(normalString , decoded);
}
this is the encoded string
YjRmYTJhMGEtYjI0ZC00ZjU4LTg2ZDktNTNiN2I2ODM4YjY3IzU1YjFjNGUzZTRiMGQ4OTUxMGM2YWEyNw
i want to generate UUID for this
You can convert as below using 2 functions. apache commons codec jar has some methods to encode and decode UUID using Base64.
Link to download apache commons codec jar: http://www.java2s.com/Code/JarDownload/apache-commons/apache-commons-codec-1.4.jar.zip
import java.nio.ByteBuffer;
import java.util.UUID;
import org.apache.commons.codec.binary.Base64;
public class Solution1 {
public static void main(String[] args) {
String uuid_str = "YjRmYTJhMGEtYjI0ZC00ZjU4LTg2ZDktNTNiN2I2ODM4YjY3IzU1YjFjNGUzZTRiMGQ4OTUxMGM2YWEyNw";
String uuid_as_64 = uuidFromBase64(uuid_str);
System.out.println("as base64: "+uuid_as_64);
System.out.println("as uuid: "+uuidFromBase64(uuid_as_64));
}
private static String uuidToBase64(String str) {
Base64 base64 = new Base64();
UUID uuid = UUID.fromString(str);
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return base64.encodeBase64URLSafeString(bb.array());
}
private static String uuidFromBase64(String str) {
Base64 base64 = new Base64();
byte[] bytes = base64.decodeBase64(str);
ByteBuffer bb = ByteBuffer.wrap(bytes);
UUID uuid = new UUID(bb.getLong(), bb.getLong());
return uuid.toString();
}
}
Output:
as base64: 62346661-3261-3061-2d62-3234642d3466
as uuid: eb6df8eb-aeb5-fb7d-bad7-edf4eb5fb677
For more, you can follow the tutorial:
http://www.baeldung.com/java-base64-encode-and-decode
http://www.tutorialspoint.com/java8/java8_base64.htm
How can I convert a UUID to base64?
Storing UUID as base64 String
The above base64 string decodes to ASCII string "b4fa2a0a-b24d-4f58-86d9-53b7b6838b67#55b1c4e3e4b0d89510c6aa27", so:
import org.apache.commons.codec.binary.Base64;
public class Solution {
private static String uuidFromBase64(String str) {
Base64 base64 = new Base64();
byte[] bytes = base64.decodeBase64(str);
String s = new String(bytes);
String trimmed = s.split("#")[0];
return trimmed;
}
}
I am trying to encrypt a Client' name (string format) storing it in a database and then retrieving it and decrypting it. As i need to avoid any third part libraries, i have used classes which are readily available with Java distribution.
The process was working fine, until I encountered a name with a special character (Ascii : 48910). This was geting displayed as a question mark(?). The encryption and descryption went fine, but after the decryption the special character was replaced with the question mark.
So i changed the Encoding format from 'UTF-8' to 'ISO-8859-1'. This solved the display problem, but still the special character gets replaced after decryption.
The code being used and the output is given below (i have removed the unnecessary code):
package crypt;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.xml.bind.DatatypeConverter;
public class SecretKeyEncryptionExample {
private static final String FORMAT = "ISO-8859-1";
public static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
private KeySpec ks;
private SecretKeyFactory skf;
private Cipher cipher;
SecretKey key;
public SecretKeyEncryptionExample() throws Exception {
String myEncryptionKey = "4A144BEBF7E5E7B7DCF26491AE79C54C768C514CF1547D23";
ks = new DESedeKeySpec(myEncryptionKey.getBytes(FORMAT));
skf = SecretKeyFactory.getInstance(DESEDE_ENCRYPTION_SCHEME);
cipher = Cipher.getInstance(DESEDE_ENCRYPTION_SCHEME);
key = skf.generateSecret(ks);
}
public String encrypt(String unencryptedString) throws Exception {
String encryptedString = null;
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainText = unencryptedString.getBytes(FORMAT);
byte[] encryptedText = cipher.doFinal(plainText);
encryptedString = DatatypeConverter.printBase64Binary(encryptedText);
return encryptedString;
}
public String decrypt(String encryptedString) throws Exception {
String decryptedText = null;
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptedText = DatatypeConverter.parseBase64Binary(encryptedString);
byte[] plainText = cipher.doFinal(encryptedText);
decryptedText = new String(plainText);
return decryptedText;
}
public static void main(String args[]) throws Exception {
SecretKeyEncryptionExample td = new SecretKeyEncryptionExample();
String target = "Expendable" + getSpecialCharacter(49810) + "s Pte Ltd";
String encrypted = td.encrypt(target);
String decrypted = td.decrypt(encrypted);
PrintStream out = new PrintStream(System.out, true, FORMAT);
out.println("String To Encrypt: " + target);
out.println("Encrypted String: " + encrypted);
out.println("Decrypted String: " + decrypted);
}
public static String getSpecialCharacter(int code) {
Charset charSet = Charset.forName(FORMAT);
String specialCharacter = new String(new byte[] { (byte) code }, charSet);
specialCharacter = String.format("%s", specialCharacter);
return specialCharacter;
}
}
OUTPUT:
String To Encrypt: Expendable’s Pte Ltd
Encrypted String: TAAJuF7KOmBZHBXFHsW0FB9YBwH7Tcif
Decrypted String: Expendable?s Pte Ltd
Please let know how the decryption can be attained, without getting the special character replaced.
I think you should specify your encoding every time you go from a string to a byte array and back. In particular, this line:
decryptedText = new String(plainText);
should read:
decryptedText = new String(plainText, FORMAT);
Otherwise you rely on your environment's encoding, which in all likelihood differs from FORMAT and result in the special character being printed as "?".
Some things which may be useful to know.
System.out.println((int) getSpecialCharacter(49810).charAt(0));
prints
146
This is the character you are actually creating here.
System.out.println("The Falcon" + (char) 146 + "s Hangar Pte Ltd");
prints
The Falcon’s Hangar Pte Ltd
I think the problem is that you get the bytes using the ISO-8859-1 character set with
byte[] plainText = unencryptedString.getBytes(FORMAT);
but when you turn it back into a String you use the system default.
decryptedText = new String(plainText);
I suspect this should be
decryptedText = new String(plainText, FORMAT); // use the same Charset
I'm implementing a simple password store using Blowfish. All was fine until I tried out a few different password/key combinations and came across numerous instances where the decrypted values were still garbage.
Below is a standalone class that demonstrates the issue. I get the following output:
'Aaaaaaa7' encrypted: 'r?—èLèdÓ,·Ã¸ÍÒ'*
'Aaaaaaa7' decrypted: 'ñü=€¼(T'*
Any idea what I need to do to guarantee it always decrypts correctly.
(Using jce.jar in JDK 1.6.0_26)
Thanks,
David
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class BlowfishTwoWayHashImpl {
static {
test();
}
public static void test() {
String key = "wibble";
String passwordToEnrypt = "Aaaaaaa7";
String enc = BlowfishTwoWayHashImpl.encryptBlowfish(passwordToEnrypt, key);
System.out.println("'" + passwordToEnrypt + "' encrypted: '" + enc + "'");
String dec = BlowfishTwoWayHashImpl.decryptBlowfish(enc, key);
System.out.println("'" + passwordToEnrypt + "' decrypted: '" + dec + "'");
}
private static final String CIPHER_NAME = "Blowfish";
public static String encryptBlowfish(String toEncrypt, String key) {
return processString(toEncrypt, key, Cipher.ENCRYPT_MODE);
}
public static String decryptBlowfish(String toDecrypt, String key) {
return processString(toDecrypt, key, Cipher.DECRYPT_MODE);
}
private static String processString(String toEncrypt, String key, int encryptDecryptMode) {
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), CIPHER_NAME);
Cipher cipher;
try {
cipher = Cipher.getInstance(CIPHER_NAME);
cipher.init(encryptDecryptMode, secretKeySpec);
return new String(cipher.doFinal(toEncrypt.getBytes()));
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
}
Don't do this:
return new String(cipher.doFinal(toEncrypt.getBytes()));
You're using the platform default encoding all over the place in your code. Don't do this. It will lose data.
When you're converting genuine text to bytes (e.g. on encryption) use a specific charset - UTF-8 is a good choice. Use the same charset to decode from "encoded text" to String.
When you're converting arbitrary binary data to text, use base64 encoding, e.g. via this public domain Base64 encoding library.
Basically, when you create a new string with the String(byte[]) or String(byte[], String) constructors, you're saying, "This is genuine text data - please just decode it as a string." When the data is actually the result of encryption, it's not text data... it's an arbitrary bunch of bytes.