Category Archives: Security

Java 8: Base64 Encoding and Decoding


In Java 8 added new class Base64 for encryption and decryption. It supports three types encoding and decoding:

  • Simple
  • URL
  • MIME

Note: Passing a null argument to a method of this class will cause a NullPointerException to be thrown.

Simple

Uses “The Base64 Alphabets” lying in A-Za-z0-9+/ for encoding and decoding. The encoder does not add any line feed/line separate character in output and decoder rejects all characters out of the Base 64 alphabet.

Example: Simple Encoding and Decoding

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64s {

	public static void main(String[] args) {
    final String text = "Facing Issues On IT in Java 8!";

        final String encoded = Base64.getEncoder().encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );
        System.out.println("After Encoding:"+ encoded );

        final String decoded = new String(Base64.getDecoder().decode( encoded ),StandardCharsets.UTF_8 );
        System.out.println("After Decoding:"+ decoded );
	}
}

Output


After Encoding:RmFjaW5nIElzc3VlcyBPbiBJVCBpbiBKYXZhIDgh
After Decoding:Facing Issues On IT in Java 8!

URL

Uses “URL and Filename safe Base64 Alphabet” lying in A-Za-z0-9+_ for encoding and decoding. The encoder does not add any line feed/line separater character in output and decoder rejects all characters out of the Base 64 alphabet.

Example: URL Encoding and Decoding

import java.util.Base64;

public class Base64URLExample {

	public static void main(String[] args) {
		String originalUrl = "https://www.google.co.in/?gfe_rd=cr&ei=dzbFV&gws_rd=ssl#q=java";
		String encodedUrl = Base64.getUrlEncoder().encodeToString(originalUrl.getBytes());
		System.out.println("After Encoding:"+ encodedUrl );

		byte[] decodedBytes = Base64.getUrlDecoder().decode(encodedUrl);
		String decodedUrl = new String(decodedBytes);
		System.out.println("After Decoding:"+ decodedUrl );
	}

}

Output


After Encoding:aHR0cHM6Ly93d3cuZ29vZ2xlLmNvLmluLz9nZmVfcmQ9Y3ImZWk9ZHpiRlYmZ3dzX3JkPXNzbCNxPWphdmE=
After Decoding:https://www.google.co.in/?gfe_rd=cr&ei=dzbFV&gws_rd=ssl#q=java

MIME

Uses “The Base64 Alphabet” lying in lying in A-Za-z0-9+/ for encoding and decoding. The encoded output must be represented in lines of no more than 76 characters each and uses a carriage return ‘\r’ followed immediately by a linefeed ‘\n’ as the line separator. No line separator is added to the end of the encoded output. All line separators or other characters not found in the base64 alphabet table are ignored in decoding operation.

Example: MIME Encoding and Decoding

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;

public class Base64Mime {

	public static void main(String[] args) {

		try {
			StringBuilder stringBuilder = new StringBuilder();
			// Lets generate some mime input to encode
			for (int i = 0; i < 10; ++i) {
				stringBuilder.append(UUID.randomUUID().toString());
			}

			byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
			String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
			System.out.println("Base64 Encoded String (MIME) :" + mimeEncodedString);

			byte[] decodedBytes = Base64.getMimeDecoder().decode(mimeEncodedString);
			String decodedMime = new String(decodedBytes);
			System.out.println("Base64 Decoded String (MIME) :" + decodedMime);

		} catch (UnsupportedEncodingException e) {
			System.out.println("Error :" + e.getMessage());
		}
	}

}

Output


Base64 Encoded String (MIME) :YWY1MWRkMDAtNjg0MC00MDE4LTk5YWYtMDE4NTFhYmZkYzA3M2Q0MjU1YjMtNDFiOS00ZmZmLTky
NjktYzc5YjU2Mzg4OGMyM2IzZTAyN2QtNzhkMC00YzRiLTg3MzgtZWFiMmI3OTdlNmVlMzdmYzQ3
ZDItYmI2Zi00NmVjLThlYTQtOWUwYWJlODA0M2IwN2I1NzIxNjUtNzJjZC00ODhmLWJkMWUtOWVl
NGI3YTc5M2NmZjczMjU1MDItMzIyNC00Mjc1LWI2MjQtNTcxZTU3ZmZkZjVhNTdiMmM4NTgtMzFi
Yi00ZjNlLWI5MWYtZWJkNjc5ODlkOTA2NDQ4MDZiZDQtOWM4Zi00NjJlLWI1ZWUtODZiNWM0MTJm
MmVjM2JmMjFjMDAtNjUwYi00ZjE0LWI5ZTUtOTY2YjE2NjUzMWQxMGJhYTIzMTAtOTFmMy00OGYz
LTg1ZTgtZmU3OTEyMjNhODc3
Base64 Decoded String (MIME) :af51dd00-6840-4018-99af-01851abfdc073d4255b3-41b9-4fff-9269-c79b563888c23b3e027d-78d0-4c4b-8738-eab2b797e6ee37fc47d2-bb6f-46ec-8ea4-9e0abe8043b07b572165-72cd-488f-bd1e-9ee4b7a793cff7325502-3224-4275-b624-571e57ffdf5a57b2c858-31bb-4f3e-b91f-ebd67989d90644806bd4-9c8f-462e-b5ee-86b5c412f2ec3bf21c00-650b-4f14-b9e5-966b166531d10baa2310-91f3-48f3-85e8-fe791223a877

References

Advertisements

How to mask JAVA Object confidential/personal information in logs while Printing


Here you will see all steps to mask confidential/ information like credit card, CVV, Exp date,  SSN, password etc. So that it will print in mask form as ****** so that unauthorize use will not misuse of others information.

Main concept to mask an Java for personal information by using reflection API and string override method by extending mask class.

Below are steps to masking Java Object :

  • Extends classes with MaskData class.
  • Override toString() method of object class and implement in MaskData Class.
  • Use JAVA reflection apis to get all fields objects and change SPI fields with *****.
  • Use replace digits methods method to replace digits with *.

Below are classes AccountDetail, Address and CredeitCard where only confidential information need to mask for Credit Card.

package com.model;

import com.mask.object.MaskData;

public class AccountDetail extends MaskData {
private String firstName;
private String lastName;
private AddressDetail address;
private CreditCardDetail creditCardDetail;
public AccountDetail(String firstName, String lastName, AddressDetail address, CreditCardDetail creditCardDetail) {
	super();
	this.firstName = firstName;
	this.lastName = lastName;
	this.address = address;
	this.creditCardDetail = creditCardDetail;
}
public String getFirstName() {
	return firstName;
}
public void setFirstName(String firstName) {
	this.firstName = firstName;
}
public String getLastName() {
	return lastName;
}
public void setLastName(String lastName) {
	this.lastName = lastName;
}
public AddressDetail getAddress() {
	return address;
}
public void setAddress(AddressDetail address) {
	this.address = address;
}
public CreditCardDetail getCreditCardDetail() {
	return creditCardDetail;
}
public void setCreditCardDetail(CreditCardDetail creditCardDetail) {
	this.creditCardDetail = creditCardDetail;
}

}

Address Class not having any confidential information.
package com.model;

import com.mask.object.MaskData;

public class AddressDetail extends MaskData{

private String addressLine1;
private String city;
private String state;
private String pincode;
private String country;

public AddressDetail(String addressLine1, String city, String state, String pincode, String country) {
	super();
	this.addressLine1 = addressLine1;
	this.city = city;
	this.state = state;
	this.pincode = pincode;
	this.country = country;
}
public String getAddressLine1() {
	return addressLine1;
}
public void setAddressLine1(String addressLine1) {
	this.addressLine1 = addressLine1;
}
public String getCity() {
	return city;
}
public void setCity(String city) {
	this.city = city;
}
public String getState() {
	return state;
}
public void setState(String state) {
	this.state = state;
}
public String getPincode() {
	return pincode;
}
public void setPincode(String pincode) {
	this.pincode = pincode;
}
public String getCountry() {
	return country;
}
public void setCountry(String country) {
	this.country = country;
}

}

CreditCardDetail class is having confidential fields cardNumber,cvv and expDate only these fields need to mask.

package com.model;

import com.mask.object.MaskData;

public class CreditCardDetail extends MaskData{
private String cardNumber;
private String cvv;
private String expDate;

public CreditCardDetail(String cardNumber, String cvv, String expDate) {
	super();
	this.cardNumber = cardNumber;
	this.cvv = cvv;
	this.expDate = expDate;
}

public String getCardNumber() {
	return cardNumber;
}
public void setCardNumber(String cardNumber) {
	this.cardNumber = cardNumber;
}
public String getCvv() {
	return cvv;
}
public void setCvv(String cvv) {
	this.cvv = cvv;
}
public String getExpDate() {
	return expDate;
}
public void setExpDate(String expDate) {
	this.expDate = expDate;
}

}

This is main class where masking these confidential fields by using JAVA reflection apis and override toString() method of Object Class.


package com.mask.object;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MaskData implements Cloneable {
	Set fieldSet=new HashSet();
	String[] spiData = { "cardNumber", "cvv", "expDate" };

	public Object clone() {
		return this;
	}

	@Override
	public String toString() {
		StringBuffer buffer=new StringBuffer();
		try
		{
		Object object=super.clone();
		printObjectStream(buffer,object);
		}
		 catch (CloneNotSupportedException ex)
		{
			 ex.printStackTrace();
		}
		return buffer.toString();
	}

	private void printObjectStream(StringBuffer buffer, Object object) {
		try {
			buffer.append(object.getClass().getCanonicalName()).append("[\n");
			Object value=null;
			for (Field field : object.getClass().getDeclaredFields()) {
				if(fieldSet.add(field.getName()))
				{
					field.setAccessible(true);
					//System.out.println(field.getName());
					buffer.append(field.getName() + "=");
					value = field.get(object);
					if(value!=null)
					{
						if(field.getType().isArray() |field.getType().getCanonicalName().startsWith("com.model"))
						{
							printObjectStream(buffer,value);
						}
						else if (Arrays.asList(spiData).contains(field.getName())) {
							//field.set(object, replaceDigits((String) field.get(object)));
							buffer.append(replaceDigits((String) value) );
						}
						else
						{
							buffer.append( value );
						}
					}
				}

				buffer.append("\n");
			}
			buffer.append("]");
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}

	}

	private String replaceDigits(String text) {
		StringBuffer buffer = new StringBuffer(text.length());
		Pattern pattern = Pattern.compile("\\d");
		Matcher matcher = pattern.matcher(text);
		while (matcher.find()) {
			matcher.appendReplacement(buffer, "X");
		}
		return buffer.toString();
	}

}

Below is Test program to above code .


package com.mask.object;
import com.model.AccountDetail;
import com.model.AddressDetail;
import com.model.CreditCardDetail;

public class MaskJavaObject {

	public static void main(String[] args) {
		AddressDetail addressDetail = new AddressDetail("Noida City Center", "Noida", "UP", "India", "20310");
		CreditCardDetail creditCardDetail = new CreditCardDetail("1234567890123456", "123", "12/90");
		AccountDetail accountDetail = new AccountDetail("Saurabh", "Gupta", addressDetail, creditCardDetail);
		System.out.println(accountDetail);
	}

}

Console Output

com.model.AccountDetail[
firstName=Saurabh
lastName=Gupta
address=com.model.AddressDetail[
addressLine1=Noida City Center
city=Noida
state=UP
pincode=India
country=20310
]
creditCardDetail=com.model.CreditCardDetail[
cardNumber=XXXXXXXXXXXXXXXX
cvv=XXX
expDate=XX/XX
]
]

Related Posts

Below are some more masking ways for different type of data like XML, JSON and printing objects before logging , sending to page or transferring over network.

Log4j2: How to Mask Logs Personal/Confidential/SPI Information

How to Mask JSON Confidential/Personal Information in logs :JAVA

How to MASK XML Confidential/Personal Data : JAVA

[Solved] javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher


Generally this exception happen while having some encrypted character which where used for URL parameter encryption.

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
	at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
	at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
	at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
	at javax.crypto.Cipher.doFinal(Cipher.java:2165)
	at security.EncryptionDecryptionURLParam.main(EncryptionDecryptionURLParam.java:51)

Solution :

Use below line of statements. Follow example below for more detail.

Not Use :

 byte[] decryptedPassword = cipher.doFinal(decodeStr.getBytes());

Use:

byte[] base64decodedTokenArr = Base64.decodeBase64(decodeStr.getBytes());
byte[] decryptedPassword = cipher.doFinal(base64decodedTokenArr);

Example :

Issues Solution

For more other JAVA/JDBC issues solution follow link JAVA/JDBC Issues.

[Solved] Exception java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/ECB/PKCS7Padding


Java 8 doesn’t support provider “AES/ECB/PKCS7Padding” .

Exception :

Exception in thread "main" java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/ECB/PKCS7Padding
	at javax.crypto.Cipher.getInstance(Cipher.java:540)
	at security.EncryptionDecryptionURLParam.main(EncryptionDecryptionURLParam.java:31)

Solution :

Java 8 doesn’t support provider “AES/ECB/PKCS7Padding” use provider as “AES/ECB/PKCS5Padding” as used in given example for Encryption and Decryption.

Examples:

 

Issues Solution

For more other JAVA/JDBC issues solution follow link JAVA/JDBC Issues.

How to do Encryption and Decryption for plain text/password in JAVA


Java code for Encryption and Decryption of plain text. In below code encrypting plain text encrypted by using Key by algorithm “AES/ECB/PKCS5Padding“ and Decryption again in plain text.

Pre-Requisite :

  • Java 7 or 8
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class EncryptionDecryption {

	public static void main(String[] args) throws Exception {
	    byte[] input = "facingissuesonit.com".getBytes();
	    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
	        0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

	    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

	    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

	    System.out.println(new String(input));

	    // Encryption pass
	    cipher.init(Cipher.ENCRYPT_MODE, key);

	    byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
	    int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
	    ctLength += cipher.doFinal(cipherText, ctLength);
	    System.out.println(new String(cipherText));
	    System.out.println(ctLength);

	    // Decryption pass
	    cipher.init(Cipher.DECRYPT_MODE, key);
	    byte[] plainText = new byte[cipher.getOutputSize(ctLength)];
	    int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0);
	    ptLength += cipher.doFinal(plainText, ptLength);
	    System.out.println(new String(plainText));
	    System.out.println(ptLength);
	  }

}

More Sample Code

For more JAVA and JDBC codes follow below links

 

JAVA Encryption and Decryption of URL Parameter


Java code for Encryption and Decryption of URL parameters.  In below code encrypting parameter as passed as token which is having (Fixed Text + Time stamp and Session ID) and encrypted by using Key by algorithm “AES/ECB/PKCS5Padding“.

Pre-requisite :

  • JAVA 8
  • Common-Codec-1.8.jar
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
public class EncryptionDecryptionURLParam {
	public static final String FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
	public static void main(String[] args) throws Exception {
		 SimpleDateFormat sdf = new SimpleDateFormat(FORMAT);
	     String timestamp = sdf.format(new Date());

	     String constantValue="FacingIssuesOnIT";
	     String sessionId="ABCDEFGHIJKLMNOPQRSTUVWXYZ";

		 String tokenStr = constantValue+"$"+timestamp+"/06$"+sessionId;

		 System.out.println(tokenStr);

	    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
	        0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

	    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

	    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

	    // encryption url
	    cipher.init(Cipher.ENCRYPT_MODE, key);

	    byte[] cipherText = cipher.doFinal(tokenStr.getBytes());
        System.out.println("encrypted token size:" + cipherText.length);
        //Encode Character which are not allowed on URL
        String encodedTxt = Base64.encodeBase64URLSafeString(cipherText);

        System.out.println("EncodedEncryptedToken : " + encodedTxt);

	    //decryption url
        cipher.init(Cipher.DECRYPT_MODE, key);
        String decodeStr = URLDecoder.decode(
        		encodedTxt,
        StandardCharsets.UTF_8.toString());
        System.out.println("URL Decoder String :"+decodeStr);
        //Decode URl safe to base 64
        byte[] base64decodedTokenArr = Base64.decodeBase64(decodeStr.getBytes());

       byte[] decryptedPassword = cipher.doFinal(base64decodedTokenArr);
        //byte[] decryptedPassword = cipher.doFinal(decodeStr.getBytes());
       String  decodeTxt=new String(decryptedPassword);
       System.out.println("Token after decryption: " + decodeTxt);

	  }

}
 

More Sample Code

For more JAVA and JDBC codes follow below links