package jenkins.security;
import hudson.util.Secret;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.GeneralSecurityException;
/**
* {@link ConfidentialKey} that stores a {@link SecretKey} for shared-secret cryptography (AES).
*
* @author Kohsuke Kawaguchi
* @since 1.498
*/
public class CryptoConfidentialKey extends ConfidentialKey {
private volatile SecretKey secret;
public CryptoConfidentialKey(String id) {
super(id);
}
public CryptoConfidentialKey(Class owner, String shortName) {
this(owner.getName()+'.'+shortName);
}
private SecretKey getKey() {
try {
if (secret==null) {
synchronized (this) {
if (secret==null) {
byte[] payload = load();
if (payload==null) {
payload = ConfidentialStore.get().randomBytes(256);
store(payload);
}
// Due to the stupid US export restriction JDK only ships 128bit version.
secret = new SecretKeySpec(payload,0,128/8, ALGORITHM);
}
}
}
return secret;
} catch (IOException e) {
throw new Error("Failed to load the key: "+getId(),e);
}
}
/**
* Returns a {@link Cipher} object for encrypting with this key.
*/
public Cipher encrypt() {
try {
Cipher cipher = Secret.getCipher(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, getKey());
return cipher;
} catch (GeneralSecurityException e) {
throw new AssertionError(e);
}
}
/**
* Returns a {@link Cipher} object for decrypting with this key.
*/
public Cipher decrypt() {
try {
Cipher cipher = Secret.getCipher(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getKey());
return cipher;
} catch (GeneralSecurityException e) {
throw new AssertionError(e);
}
}
private static final String ALGORITHM = "AES";
}