Coverage Summary for Class: JasyptPasswordEncryptor (com.acciente.oacc.encryptor.jasypt)

Class Class, % Method, % Line, %
JasyptPasswordEncryptor 100% (1/ 1) 100% (6/ 6) 100% (24/ 24)


1 /* 2  * Copyright 2009-2018, Acciente LLC 3  * 4  * Acciente LLC licenses this file to you under the 5  * Apache License, Version 2.0 (the "License"); you 6  * may not use this file except in compliance with the 7  * License. You may obtain a copy of the License at 8  * 9  * http://www.apache.org/licenses/LICENSE-2.0 10  * 11  * Unless required by applicable law or agreed to in 12  * writing, software distributed under the License is 13  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 14  * OR CONDITIONS OF ANY KIND, either express or implied. 15  * See the License for the specific language governing 16  * permissions and limitations under the License. 17  */ 18 package com.acciente.oacc.encryptor.jasypt; 19  20 import com.acciente.oacc.encryptor.PasswordEncryptor; 21 import com.acciente.oacc.normalizer.TextNormalizer; 22  23 import java.io.Serializable; 24 import java.nio.ByteBuffer; 25 import java.nio.CharBuffer; 26 import java.nio.charset.StandardCharsets; 27 import java.util.Arrays; 28  29 /** 30  * Password encryptor implementation that uses the Jasypt digester for creating password hashes. 31  */ 32 public final class JasyptPasswordEncryptor implements PasswordEncryptor, Serializable { 33  private static final long serialVersionUID = 1L; 34  35  public static final String NAME = "jasypt"; 36  37  private static final StandardByteDigesterPool digesterPool = new StandardByteDigesterPool(); 38  private static final PasswordEncoderDecoder passwordEncoderDecoder = new PasswordEncoderDecoder(); 39  40  private final String algorithm; 41  private final int iterations; 42  private final int saltSizeBytes; 43  44  /** 45  * Creates a password encryptor that uses the Jasypt digester for password hashing with the specified values for 46  * algorithm, iterations and saltSizeBytes. 47  * 48  * @param algorithm the name of the message digest algorithm to be used for password hashing. 49  * See the MessageDigest section in the <a href= 50  * "https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest"> 51  * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 52  * for information about standard algorithm names. 53  * @param iterations the number of times the password hash function will be applied recursively 54  * @param saltSizeBytes the size of the salt to be used, in bytes 55  * @return a {@link JasyptPasswordEncryptor} instance. 56  */ 57  public static JasyptPasswordEncryptor newInstance(String algorithm, 58  int iterations, 59  int saltSizeBytes) { 60  return new JasyptPasswordEncryptor(algorithm, iterations, saltSizeBytes); 61  } 62  63  private JasyptPasswordEncryptor(String algorithm, int iterations, int saltSizeBytes) { 64  this.algorithm = algorithm; 65  this.iterations = iterations; 66  this.saltSizeBytes = saltSizeBytes; 67  } 68  69  @Override 70  public String encryptPassword(final char[] plainPassword) { 71  if (plainPassword == null) { 72  return null; 73  } 74  75  final byte[] digest = digesterPool.getStandardByteDigester(algorithm, iterations, saltSizeBytes) 76  .digest(getCleanedBytes(plainPassword)); 77  78  return passwordEncoderDecoder.encode(algorithm, iterations, saltSizeBytes, digest); 79  } 80  81  @Override 82  public boolean checkPassword(final char[] plainPassword, 83  final String storedPassword) { 84  if (plainPassword == null) { 85  return (storedPassword == null); 86  } 87  else if (storedPassword == null) { 88  return false; 89  } 90  91  final DecodedPassword decodedPassword = passwordEncoderDecoder.decode(storedPassword); 92  return digesterPool.getStandardByteDigester(decodedPassword.getAlgorithm(), 93  decodedPassword.getIterations(), 94  decodedPassword.getSaltSizeBytes()) 95  .matches(getCleanedBytes(plainPassword), decodedPassword.getDigest()); 96  } 97  98  private static byte[] getCleanedBytes(char[] password) { 99  final char[] normalizedChars = TextNormalizer.getInstance().normalizeToNfc(password); 100  final ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(CharBuffer.wrap(normalizedChars)); 101  final byte[] byteArray = new byte[byteBuffer.remaining()]; 102  byteBuffer.get(byteArray); 103  Arrays.fill(byteBuffer.array(), (byte) 0); 104  return byteArray; 105  } 106 }