Home > Blockchain >  Finding a field and replacing the first 16 digits of the field_value [string] with Regex
Finding a field and replacing the first 16 digits of the field_value [string] with Regex

Time:08-16

I am able to find similar question here on the site but not one specific that will help me fix my issue. I want to mask all but the last 4 digits of cardNo value coming in the request while Logging. Ex. if it is "cardNo":"10929291929312911131" then it should be logged as "cardNo":"XXXXXXXXXXXXXXXX1131. There can be two ways, cardNo is present in the request:

  1. "cardNo":"10929291929312911131"
  2. (cardNo:"10929291929312911131",cardType:"CREDIT")

Kindly, help me to correct my regex so that above patterns are captured.

  import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import org.apache.logging.log4j.core.*;
    
    @Plugin(name = "LogMaskingConverter", category = "Convertor")
    @ConvertorKeys({ "mask" })
    public class LogMaskingConverter extend LogEventPatternConverter {
    
        private static final Pattern SENSITIVE_DATA_PATTERN = Pattern.compile("(?<=\\bcardNo*)\\b*[0-9] {16}\\b");
    
        private static final String REPLACEMENT_REGEX = "$1$2XXXXXXXXXXXXXXXX$3";
    
        protected LogMaskingConverter(String name, String style) {
            super(name, style);
        }
    
        public static LogMaskingConverter newInstance(String[] options) {
            return new LogMaskingConverter("mask", Thread.currentThread().getName());
        }
    
        @Override
        public void format(LogEvent event, StringBuilder outputMessage) {
            String message = event.getMessage().getFormattedMessage();
            String maskedMessage;
            try {
                maskedMessage = mask(message);
            } catch (Exception e) {
                maskedMessage = message;
            }
            outputMessage.append(maskedMessage);
        }
    
        private String mask(String message) {
            StringBuffer buffer = new StringBuffer();
            maskMatcher(SENSITIVE_DATA_PATTERN.matcher(message), buffer);
            return buffer.toString();
        }
    
        private StringBuffer maskMatcher(Matcher matcher, StringBuffer buffer) {
            while (matcher.find()) {
                matcher.appendReplacement(buffer, REPLACEMENT_REGEX);
            }
            matcher.appendTail(buffer);
            return buffer;
        }
    }

Edit 1:

There may or may not be space on either side of the colon. Could you please suggest: 1."cardNo" : "10929291929312911131" 2.creditCardData(cardNo: "10929291929312911131",cardType:"CREDIT") –

CodePudding user response:

Using Java, you might use a lookbehind with a finite quantifier asserting a certain amount of digits before matching the single digit to replace:

(?<=cardNo\"?\s?:\s?\"\d{0,100})\d(?!\d{0,3}\")

Explanation

  • (?<= Positive lookahead, assert what is to the left is
    • cardNo\"?\s?:\s? Match cardNo, optional "`, optional whitespace char
    • \"\d{0,100} Match " and for example 0-100 digits that can precede
  • ) Close the lookbehind
  • \d Match a single digit (which will be replaced by X)
  • (?!\d{0,3}\") Negative lookahead, assert not 0-3 times a digit to the right followed by "

In the replacement use X

See a Regex demo and a Java demo

  • Related