package it.geosolutions.geostore.core.security.password;
/*
* Copyright (C) 2007 - 2011 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import static it.geosolutions.geostore.core.security.password.SecurityUtils.scramble;
import static it.geosolutions.geostore.core.security.password.SecurityUtils.toBytes;
import static it.geosolutions.geostore.core.security.password.SecurityUtils.toChars;
import java.io.IOException;
import java.util.Arrays;
import org.jasypt.encryption.pbe.StandardPBEByteEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.spring.security3.PBEPasswordEncoder;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.crypto.codec.Base64;
/**
* Password Encoder using symmetric encryption
*
* The salt parameter is not used, this implementation computes a random salt as
* default.
*
* {@link #isPasswordValid(String, String, Object)}
* {@link #encodePassword(String, Object)}
*
* @author Lorenzo Natali
*
*/
public class GeoStorePBEPasswordEncoder extends AbstractGeoStorePasswordEncoder {
StandardPBEStringEncryptor stringEncrypter;
StandardPBEByteEncryptor byteEncrypter;
private String providerName, algorithm;
private String keyAliasInKeyStore = KeyStoreProviderImpl.CONFIGPASSWORDKEY;
private KeyStoreProvider keystoreProvider;
public KeyStoreProvider getKeystoreProvider() {
return keystoreProvider;
}
public void setKeystoreProvider(KeyStoreProvider keystoreProvider) {
this.keystoreProvider = keystoreProvider;
}
public void setKeyAliasInKeyStore(String keyAliasInKeyStore) {
this.keyAliasInKeyStore = keyAliasInKeyStore;
}
public String getProviderName() {
return providerName;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
public String getAlgorithm() {
return algorithm;
}
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
public String getKeyAliasInKeyStore() {
return keyAliasInKeyStore;
}
@Override
protected PasswordEncoder createStringEncoder() {
byte[] password = lookupPasswordFromKeyStore();
char[] chars = toChars(password);
try {
stringEncrypter = new StandardPBEStringEncryptor();
stringEncrypter.setPasswordCharArray(chars);
if (getProviderName() != null && !getProviderName().isEmpty()) {
stringEncrypter.setProviderName(getProviderName());
}
stringEncrypter.setAlgorithm(getAlgorithm());
PBEPasswordEncoder encoder = new PBEPasswordEncoder();
encoder.setPbeStringEncryptor(stringEncrypter);
return encoder;
} finally {
scramble(password);
scramble(chars);
}
}
@Override
protected CharArrayPasswordEncoder createCharEncoder() {
byte[] password = lookupPasswordFromKeyStore();
char[] chars = toChars(password);
byteEncrypter = new StandardPBEByteEncryptor();
byteEncrypter.setPasswordCharArray(chars);
if (getProviderName() != null && !getProviderName().isEmpty()) {
byteEncrypter.setProviderName(getProviderName());
}
byteEncrypter.setAlgorithm(getAlgorithm());
return new CharArrayPasswordEncoder() {
@Override
public boolean isPasswordValid(String encPass, char[] rawPass,
Object salt) {
byte[] decoded = Base64.decode(encPass.getBytes());
byte[] decrypted = byteEncrypter.decrypt(decoded);
char[] chars = toChars(decrypted);
try {
return Arrays.equals(chars, rawPass);
} finally {
scramble(decrypted);
scramble(chars);
}
}
@Override
public String encodePassword(char[] rawPass, Object salt) {
byte[] bytes = toBytes(rawPass);
try {
return new String(Base64.encode(byteEncrypter
.encrypt(bytes)));
} finally {
scramble(bytes);
}
}
};
}
byte[] lookupPasswordFromKeyStore() {
try {
if (!keystoreProvider.containsAlias(getKeyAliasInKeyStore())) {
throw new RuntimeException("Keystore: "
+ keystoreProvider.getFile() + " does not"
+ " contain alias: " + getKeyAliasInKeyStore());
}
return keystoreProvider.getSecretKey(getKeyAliasInKeyStore())
.getEncoded();
} catch (IOException e) {
throw new RuntimeException("Cannot find alias: "
+ getKeyAliasInKeyStore() + " in "
+ keystoreProvider.getFile().getAbsolutePath());
}
}
@Override
public PasswordEncodingType getEncodingType() {
return PasswordEncodingType.ENCRYPT;
}
public String decode(String encPass) throws UnsupportedOperationException {
if (stringEncrypter == null) {
// not initialized
getStringEncoder();
}
return stringEncrypter.decrypt(removePrefix(encPass));
}
@Override
public char[] decodeToCharArray(String encPass)
throws UnsupportedOperationException {
if (byteEncrypter == null) {
// not initialized
getCharEncoder();
}
byte[] decoded = Base64.decode(removePrefix(encPass).getBytes());
byte[] bytes = byteEncrypter.decrypt(decoded);
try {
return toChars(bytes);
} finally {
scramble(bytes);
}
}
}