Tag Archives: Mask Confidential Information

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


You can configure Log4j2 LogEventConverter plugin for masking personal/ confidential/ SPI data. For example here we are masking credit card number, SSN and CVV of log statements.

Below Log4j2 dependencies you need to add with your application.

Pre-Requisite

Log4j2 Dependency

pom.xml entry


         <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.6.1</version>
        </dependency>
   

Log4j2.xml Configuration File

Below is basic console based configuration for masking where packages used for where loggers need to apply and masking plugin annotation as in below program. In PatternLayout used key as spi which is map with plugin which will mask log text and print as message.


<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://logging.apache.org/log4j/2.0/config"
       status="OFF" packages="com.mask.logs">
       <Appenders>
    <Console name="STDOUT" target="SYSTEM_OUT">
     <PatternLayout pattern="%d{yyyyMMdd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %spi%n"/>
   
    </Console>
  </Appenders>
  <loggers>
              <Logger name="org.apache.log4j.xml" level="all" />
              <root level="all">
                     <appender-ref ref="STDOUT" level="TRACE" />
                     </root>
  </loggers>
</configuration>

To know more about log4j2 configuration follow below link:

Log4j2 Java Logging Example Tutorial – XML Configuration, Severity Levels, Formatting and Appenders

Log4j2 Plugin Code for Masking

Created this LogMakingConverter Plug in for masking logs statement
Here masking for Credit card number, CVV and SSN . You can also implement for password and rest depend on your application needs. Here we have used Java regular expression Mater and Pattern apis for maskin and also different character as +++ for CVV,********* for SSN and **************** for credit card by matching number of digits in log lines.

package com.mask.logs;
/**
 * Created this LogMakingConverter Plug in for masking logs statement
 * Here masking for Credit card number, CVV and SSN .
 * You can also implement for password and rest depend on your application needs.
 */
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;

@Plugin(name="LogMaskingConverter", category = "Converter")
@ConverterKeys({"spi","trscId"})
public class LogMaskingConverter extends LogEventPatternConverter{
	private static final String CREDIT_CARD_REGEX = "([0-9]{16})";;
	private static final Pattern CREDIT_CARD_PATTERN = Pattern.compile(CREDIT_CARD_REGEX);
	private static final String CAREDIT_CARD_REPLACEMENT_REGEX = "XXXXXXXXXXXXXXXX";

	private static final String CVV_REGEX = "([0-9]{3})";
	private static final Pattern CVV_PATTERN = Pattern.compile(CVV_REGEX);
	private static final String CVV_REPLACEMENT_REGEX = "+++";

	private static final String SSN_REGEX = "([0-9]{9})";
	private static final Pattern SSN_PATTERN = Pattern.compile(SSN_REGEX);
	private static final String SSN_REPLACEMENT_REGEX = "*********";

    protected LogMaskingConverter(String name, String style) {
        super(name, style);
    }

    public static LogMaskingConverter newInstance(String[] options) {
        return new LogMaskingConverter("spi",Thread.currentThread().getName());
    }

    @Override
    public void format(LogEvent event, StringBuilder outputMessage) {
    	String message = event.getMessage().getFormattedMessage();
		String maskedMessage = message;
		try {
			maskedMessage = mask(message);
		} catch (Exception e) {
			System.out.println("Failed While Masking");
			maskedMessage = message;
		}
		outputMessage.append(maskedMessage);	

    }

    private String mask(String message) {
    	Matcher matcher =null;
		StringBuffer buffer = new StringBuffer();

		matcher = CREDIT_CARD_PATTERN.matcher(message);
		maskMatcher(matcher, buffer,CAREDIT_CARD_REPLACEMENT_REGEX);
		message=buffer.toString();
		buffer.setLength(0);

		matcher = SSN_PATTERN.matcher(message);
		maskMatcher(matcher, buffer,SSN_REPLACEMENT_REGEX);
		message=buffer.toString();
		buffer.setLength(0);

		matcher = CVV_PATTERN.matcher(message);
		maskMatcher(matcher, buffer,CVV_REPLACEMENT_REGEX);

		return buffer.toString();
	}

    private StringBuffer maskMatcher(Matcher matcher, StringBuffer buffer, String maskStr)
    {
    	while (matcher.find()) {
			matcher.appendReplacement(buffer,maskStr);
		}
		matcher.appendTail(buffer);
    	return buffer;
    }

}

Masking Test Program

Below is test program to print some log statements which are converting by Log4j2.

package com.mask.logs;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MaskingTest {
	  private static final Logger logger = LogManager.getLogger(MaskingTest.class);
      public static void myTest(){
             logger.info("this is my info message");
             logger.debug("This is debug message");
             logger.debug("Passed to server::0084USER:17603,IP:0:0:0:0:0:0:0:1,3425,Credit Card 1:1000002367844224,3425,Credit Card2:1000002367844224 , CVV:234,SSN:123456789");

      }
      public static void main(String[] args) {
             myTest();
      }
}

Output

Below is mask logs by log4j2 for confidential/personal/spi data.

20180607 11:20:43.558 [main] INFO  com.mask.logs.MaskingTest - this is my info message
20180607 11:20:43.559 [main] DEBUG com.mask.logs.MaskingTest - This is debug message
20180607 11:20:43.560 [main] DEBUG com.mask.logs.MaskingTest - Passed to server::+++4USER:+++03,IP:0:0:0:0:0:0:0:1,+++5,Credit Card 1:XXXXXXXXXXXXXXXX,+++5,Credit Card2:XXXXXXXXXXXXXXXX , CVV:+++,SSN:
*********

Summary

  • Step by step program for masking sensitive information in logs.
  • Log4j2 XML Configuration for loggers and appenders for masking.
  • LogMaskingConverter Log4j2 plugin for masking log statements.
  • Regular expression for Creditcard, SSN and CVV.
  • Test program to write logs  by java logging api to write in logs file.

More 

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.

How to MASK XML Confidential/Personal Data : JAVA


Here you will see all steps to mask confidential/ information in XML 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.

Pre- Requisite

Use below library or add in pom.xml.


<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.10.2</version>
</dependency>

Here is same XML file as AccountDetail.xml where need to mask cardNumber, cvv and expDate .



<AccountList>
    <Account>
        <id>E001</id>
        <FirstName>Saurabh</FirstName>
        <LastName>Gupta</LastName>
        <AddressDetail>
            <AddressLine1>Noida City Center</AddressLine1>
            <City>Noida</City>
            <State>UP</State>
            <Pincode>201301</Pincode>
            <Contry>India</Contry>
        </AddressDetail>
        <CreditCardDetail>
            <CardNumber>1233454565676567</CardNumber>
            <CVV>456</CVV>
            <ExpDate>12/90</ExpDate>
        </CreditCardDetail>
    </Account>
    <Account>
        <id>E002</id>
        <FirstName>Ankur</FirstName>
        <LastName>Mehrotra</LastName>
        <AddressDetail>
            <AddressLine1>New Delhi Metro Station</AddressLine1>
            <City>New Delhi</City>
            <State>UP</State>
            <Pincode>210345</Pincode>
            <Contry>India</Contry>
        </AddressDetail>
        <CreditCardDetail>
            <CardNumber>8967452312123456</CardNumber>
            <CVV>876</CVV>
            <ExpDate>09/83</ExpDate>
        </CreditCardDetail>
    </Account>
    <Account>
        <id>E003</id>
        <FirstName>Shailesh</FirstName>
        <LastName>Nagar</LastName>
        <AddressDetail>
            <AddressLine1>Dwarka Metro Station</AddressLine1>
            <City>Delhi</City>
            <State>Delhi</State>
            <Pincode>345876</Pincode>
            <Contry>India</Contry>
        </AddressDetail>
        <CreditCardDetail>
            <CardNumber>9078563412345678</CardNumber>
            <CVV>986</CVV>
            <ExpDate>08/99</ExpDate>
        </CreditCardDetail>
    </Account>
</AccountList>

Java code to mask above XML. In below code cardNumber is masking partially so that show last four digits only and hide rest of numbers while cvv and exp date digits are masked completely.

package com.mask.xml;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;

public class MaskXML {

	public static void main(String[] args) {

		try {
			FileInputStream inputStream = new FileInputStream(
					new File("D:\\Saurabh Gupta\\Workspace\\JavaTestExamples\\src\\main\\resources\\UserAccountDetail.xml"));
			Document doc = Jsoup.parse(inputStream, "UTF-8", "", Parser.xmlParser());
			Elements toMaskTagCompletely = doc.select("Pincode,ExpDate,CVV");
			Elements toMaskTagPartially = doc.select("CardNumber");
			for (Element element : toMaskTagCompletely) {
				element.text(replaceDigits(element.text()));
			}
			for (Element element : toMaskTagPartially) {
				element.text("XXXXXXXXXXXX" + element.text().substring(element.text().length() - 4));
			}
			System.out.println(doc.toString());
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		}

	}

	private static 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();
	}

}

Result : Masked XML


<?xml version="1.0" encoding="UTF-8"?> 
<AccountList> 
 <Account> 
  <id>
   E001
  </id> 
  <FirstName>
   Saurabh
  </FirstName> 
  <LastName>
   Gupta
  </LastName> 
  <AddressDetail> 
   <AddressLine1>
    Noida City Center
   </AddressLine1> 
   <City>
    Noida
   </City> 
   <State>
    UP
   </State> 
   <Pincode>
    XXXXXX
   </Pincode> 
   <Contry>
    India
   </Contry> 
  </AddressDetail> 
  <CreditCardDetail> 
   <CardNumber>
    XXXXXXXXXXXX6567
   </CardNumber> 
   <CVV>
    XXX
   </CVV> 
   <ExpDate>
    XX/XX
   </ExpDate> 
  </CreditCardDetail> 
 </Account> 
 <Account> 
  <id>
   E002
  </id> 
  <FirstName>
   Ankur
  </FirstName> 
  <LastName>
   Mehrotra
  </LastName> 
  <AddressDetail> 
   <AddressLine1>
    New Delhi Metro Station
   </AddressLine1> 
   <City>
    New Delhi
   </City> 
   <State>
    UP
   </State> 
   <Pincode>
    XXXXXX
   </Pincode> 
   <Contry>
    India
   </Contry> 
  </AddressDetail> 
  <CreditCardDetail> 
   <CardNumber>
    XXXXXXXXXXXX3456
   </CardNumber> 
   <CVV>
    XXX
   </CVV> 
   <ExpDate>
    XX/XX
   </ExpDate> 
  </CreditCardDetail> 
 </Account> 
 <Account> 
  <id>
   E003
  </id> 
  <FirstName>
   Shailesh
  </FirstName> 
  <LastName>
   Nagar
  </LastName> 
  <AddressDetail> 
   <AddressLine1>
    Dwarka Metro Station
   </AddressLine1> 
   <City>
    Delhi
   </City> 
   <State>
    Delhi
   </State> 
   <Pincode>
    XXXXXX
   </Pincode> 
   <Contry>
    India
   </Contry> 
  </AddressDetail> 
  <CreditCardDetail> 
   <CardNumber>
    XXXXXXXXXXXX5678
   </CardNumber> 
   <CVV>
    XXX
   </CVV> 
   <ExpDate>
    XX/XX
   </ExpDate> 
  </CreditCardDetail> 
 </Account> 
</AccountList>

Summary

  • Example for mask XML.
  • Shared API and source code for masking XML in less code.
  • Shared code for Mask complete and partial text data for credit card, SSN, CVV etc.

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 JAVA Object confidential/personal information in logs while Printing

 

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


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.

Here using Google GSON and GsonBuilder converting Java object to JSON and again converting JSON to Java Object.

By using Java refelection api’s replacing SPI fields data with *******.

Input JSON File AccountDetail


{
  "firstName": "Saurabh",
  "lastName": "Gupta",
  "address": {
    "addressLine1": "Noida City Center",
    "city": "Noida",
    "state": "UP",
    "pincode": "India",
    "country": "20310"
  },
  "creditCardDetail": {
    "cardNumber": "1234567890123456",
    "cvv": "123",
    "expDate": "12/90"
  }
}

 

Code to Mask JSON

package com.mask.json;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class MaskJSONTest {
	static Set fieldSet = new HashSet();
	static List fieldNames = Arrays.asList("cardNumber", "cvv", "expDate");

	public static void main(String[] args) throws IOException {
		StringBuilder contentBuilder = new StringBuilder();
		try (Stream stream = Files.lines(
				Paths.get(
						"D:\\Saurabh Gupta\\Workspace\\JavaTestExamples\\src\\main\\resources\\AccountDetail.json"),
				StandardCharsets.UTF_8)) {
			stream.forEach(s -> contentBuilder.append(s).append("\n"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		//Create GSON object
		//apply NullSearialization and Pretty formatting by GSON Builder
		Gson gson = getJsonBuilder().create();
		AccountDetail accounDetail = gson.fromJson(contentBuilder.toString(), AccountDetail.class);
		mask(accounDetail);
		System.out.println(gson.toJson(accounDetail));
	}
	public static GsonBuilder getJsonBuilder()
	{
		GsonBuilder builder = new GsonBuilder();

		// Setting for formatted output and serialize null value
		builder.setPrettyPrinting().serializeNulls();

		return builder;
	}

	public static void mask(Object object) {
		try {
			Field[] fields = object.getClass().getDeclaredFields();
			Object value = null;
			for (int i = 0; i <span id="mce_SELREST_start" style="overflow: hidden; line-height: 0;"></span>< fields.length; i++) {
				fields[i].setAccessible(true);
				value = fields[i].get(object);
				if (value != null && fieldSet.add(fields[i].getName())) {
					if (fields[i].getType().isArray()
							|| fields[i].getType().getCanonicalName().startsWith("com.mask.json")) {
						mask(value);
					} else {
						if (fieldNames.contains(fields[i].getName()) && fields[i].get(object) != null) {
							fields[i].set(object, replaceDigits((String) fields[i].get(object)));
						}
					}
				}

			}
		} catch (IllegalAccessException ex) {
			ex.printStackTrace();
		}
	}

	private static 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();
	}

}

Model Classes


package com.mask.json;

public class AccountDetail {
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;
}

}


package com.mask.json;

public class AddressDetail {

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

}

package com.mask.json;

public class CreditCardDetail{
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;
}

}

Output Masked JSON :

{
"firstName": "Saurabh",
"lastName": "Gupta",
"address": {
"addressLine1": "Noida City Center",
"city": "Noida",
"state": "UP",
"pincode": "India",
"country": "20310"
},
"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 XML Confidential/Personal Data : JAVA

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

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