blob: e592eaf6259d1d44775ef05da0bb1dfc493b0233 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.googlesource.gerrit.plugins.secureconfig;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
@Singleton
public class PBECodec implements Codec {
private static final Logger log = LoggerFactory.getLogger(PBECodec.class);
byte[] salt = new byte[] {0x7d, 0x60, 0x43, 0x5f, 0x02, (byte) 0xe9,
(byte) 0xe0, (byte) 0xae};
private static final int iterationCount = 2048;
private final SecureConfigSettings config;
@Inject
public PBECodec(SecureConfigSettings config) {
Provider provider = Security.getProvider(config.getJCEProvider());
Security.addProvider(provider);
this.config = config;
}
@Override
public String encode(String s) {
try {
Key sKey = generateKey();
Cipher encoder = getCipher();
encoder.init(Cipher.ENCRYPT_MODE, sKey, getCipherParameterSpec());
return new String(Base64.getEncoder().encodeToString(
encoder.doFinal(s.getBytes(config.getEncoding()))));
} catch (Exception e) {
log.error("encode() failed", e);
throw new IllegalArgumentException("encode() failed", e);
}
}
@Override
public String decode(String s) {
try {
Cipher encoder = getCipher();
Key sKey = generateKey();
encoder.init(Cipher.DECRYPT_MODE, sKey, getCipherParameterSpec());
return new String(encoder.doFinal(Base64.getDecoder().decode(s)),
config.getEncoding());
} catch (Exception e) {
log.error("decode() failed", e);
throw new IllegalArgumentException("encode() failed", e);
}
}
private PBEParameterSpec getCipherParameterSpec() {
return new PBEParameterSpec(salt, iterationCount);
}
private Cipher getCipher() throws NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException {
@SuppressWarnings("InsecureCipherMode")
Cipher encoder =
Cipher.getInstance(config.getCipher(), config.getJCEProvider());
return encoder;
}
private Key generateKey() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeySpecException {
PBEKeySpec pbeSpec = new PBEKeySpec(config.getPassword());
SecretKeyFactory keyFact =
SecretKeyFactory.getInstance(config.getCipher(),
config.getJCEProvider());
return keyFact.generateSecret(pbeSpec);
}
}