use of sun.security.pkcs.EncryptedPrivateKeyInfo in project Bytecoder by mirkosertic.
the class KeyProtector method protect.
/*
* Protects the given plaintext key, using the password provided at
* construction time.
*/
public byte[] protect(Key key) throws KeyStoreException {
int i;
int numRounds;
byte[] digest;
// offset in xorKey where next digest will be stored
int xorOffset;
int encrKeyOffset = 0;
if (key == null) {
throw new IllegalArgumentException("plaintext key can't be null");
}
if (!"PKCS#8".equalsIgnoreCase(key.getFormat())) {
throw new KeyStoreException("Cannot get key bytes, not PKCS#8 encoded");
}
byte[] plainKey = key.getEncoded();
if (plainKey == null) {
throw new KeyStoreException("Cannot get key bytes, encoding not supported");
}
// Determine the number of digest rounds
numRounds = plainKey.length / DIGEST_LEN;
if ((plainKey.length % DIGEST_LEN) != 0)
numRounds++;
// Create a random salt
byte[] salt = new byte[SALT_LEN];
SecureRandom random = new SecureRandom();
random.nextBytes(salt);
// Set up the byte array which will be XORed with "plainKey"
byte[] xorKey = new byte[plainKey.length];
// Compute the digests, and store them in "xorKey"
for (i = 0, xorOffset = 0, digest = salt; i < numRounds; i++, xorOffset += DIGEST_LEN) {
md.update(passwdBytes);
md.update(digest);
digest = md.digest();
md.reset();
// Copy the digest into "xorKey"
if (i < numRounds - 1) {
System.arraycopy(digest, 0, xorKey, xorOffset, digest.length);
} else {
System.arraycopy(digest, 0, xorKey, xorOffset, xorKey.length - xorOffset);
}
}
// XOR "plainKey" with "xorKey", and store the result in "tmpKey"
byte[] tmpKey = new byte[plainKey.length];
for (i = 0; i < tmpKey.length; i++) {
tmpKey[i] = (byte) (plainKey[i] ^ xorKey[i]);
}
// Store salt and "tmpKey" in "encrKey"
byte[] encrKey = new byte[salt.length + tmpKey.length + DIGEST_LEN];
System.arraycopy(salt, 0, encrKey, encrKeyOffset, salt.length);
encrKeyOffset += salt.length;
System.arraycopy(tmpKey, 0, encrKey, encrKeyOffset, tmpKey.length);
encrKeyOffset += tmpKey.length;
// Append digest(password, plainKey) as an integrity check to "encrKey"
md.update(passwdBytes);
Arrays.fill(passwdBytes, (byte) 0x00);
passwdBytes = null;
md.update(plainKey);
digest = md.digest();
md.reset();
System.arraycopy(digest, 0, encrKey, encrKeyOffset, digest.length);
// wrap the protected private key in a PKCS#8-style
// EncryptedPrivateKeyInfo, and returns its encoding
AlgorithmId encrAlg;
try {
encrAlg = new AlgorithmId(new ObjectIdentifier(KEY_PROTECTOR_OID));
return new EncryptedPrivateKeyInfo(encrAlg, encrKey).getEncoded();
} catch (IOException ioe) {
throw new KeyStoreException(ioe.getMessage());
}
}
use of sun.security.pkcs.EncryptedPrivateKeyInfo in project jdk8u_jdk by JetBrains.
the class PKCS12KeyStore method engineGetKey.
/**
* Returns the key associated with the given alias, using the given
* password to recover it.
*
* @param alias the alias name
* @param password the password for recovering the key
*
* @return the requested key, or null if the given alias does not exist
* or does not identify a <i>key entry</i>.
*
* @exception NoSuchAlgorithmException if the algorithm for recovering the
* key cannot be found
* @exception UnrecoverableKeyException if the key cannot be recovered
* (e.g., the given password is wrong).
*/
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
Key key = null;
if (entry == null || (!(entry instanceof KeyEntry))) {
return null;
}
// get the encoded private key or secret key
byte[] encrBytes = null;
if (entry instanceof PrivateKeyEntry) {
encrBytes = ((PrivateKeyEntry) entry).protectedPrivKey;
} else if (entry instanceof SecretKeyEntry) {
encrBytes = ((SecretKeyEntry) entry).protectedSecretKey;
} else {
throw new UnrecoverableKeyException("Error locating key");
}
byte[] encryptedKey;
AlgorithmParameters algParams;
ObjectIdentifier algOid;
try {
// get the encrypted private key
EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(encrBytes);
encryptedKey = encrInfo.getEncryptedData();
// parse Algorithm parameters
DerValue val = new DerValue(encrInfo.getAlgorithm().encode());
DerInputStream in = val.toDerInputStream();
algOid = in.getOID();
algParams = parseAlgParameters(algOid, in);
} catch (IOException ioe) {
UnrecoverableKeyException uke = new UnrecoverableKeyException("Private key not stored as " + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
uke.initCause(ioe);
throw uke;
}
try {
byte[] keyInfo;
while (true) {
try {
// Use JCE
SecretKey skey = getPBEKey(password);
Cipher cipher = Cipher.getInstance(mapPBEParamsToAlgorithm(algOid, algParams));
cipher.init(Cipher.DECRYPT_MODE, skey, algParams);
keyInfo = cipher.doFinal(encryptedKey);
break;
} catch (Exception e) {
if (password.length == 0) {
// Retry using an empty password
// without a NULL terminator.
password = new char[1];
continue;
}
throw e;
}
}
/*
* Parse the key algorithm and then use a JCA key factory
* to re-create the key.
*/
DerValue val = new DerValue(keyInfo);
DerInputStream in = val.toDerInputStream();
int i = in.getInteger();
DerValue[] value = in.getSequence(2);
AlgorithmId algId = new AlgorithmId(value[0].getOID());
String keyAlgo = algId.getName();
// decode private key
if (entry instanceof PrivateKeyEntry) {
KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
key = kfac.generatePrivate(kspec);
if (debug != null) {
debug.println("Retrieved a protected private key (" + key.getClass().getName() + ") at alias '" + alias + "'");
}
// decode secret key
} else {
byte[] keyBytes = in.getOctetString();
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, keyAlgo);
// Special handling required for PBE: needs a PBEKeySpec
if (keyAlgo.startsWith("PBE")) {
SecretKeyFactory sKeyFactory = SecretKeyFactory.getInstance(keyAlgo);
KeySpec pbeKeySpec = sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class);
key = sKeyFactory.generateSecret(pbeKeySpec);
} else {
key = secretKeySpec;
}
if (debug != null) {
debug.println("Retrieved a protected secret key (" + key.getClass().getName() + ") at alias '" + alias + "'");
}
}
} catch (Exception e) {
UnrecoverableKeyException uke = new UnrecoverableKeyException("Get Key failed: " + e.getMessage());
uke.initCause(e);
throw uke;
}
return key;
}
use of sun.security.pkcs.EncryptedPrivateKeyInfo in project jdk8u_jdk by JetBrains.
the class PKCS12SameKeyId method main.
public static void main(String[] args) throws Exception {
// Prepare a JKS keystore with many entries
new File(JKSFILE).delete();
for (int i = 0; i < SIZE; i++) {
System.err.print(".");
String cmd = "-keystore " + JKSFILE + " -storepass changeit -keypass changeit -keyalg rsa " + "-genkeypair -alias p" + i + " -dname CN=" + i;
sun.security.tools.keytool.Main.main(cmd.split(" "));
}
// Prepare EncryptedPrivateKeyInfo parameters, copied from various
// places in PKCS12KeyStore.java
AlgorithmParameters algParams = AlgorithmParameters.getInstance("PBEWithSHA1AndDESede");
algParams.init(new PBEParameterSpec("12345678".getBytes(), 1024));
AlgorithmId algid = new AlgorithmId(new ObjectIdentifier("1.2.840.113549.1.12.1.3"), algParams);
PBEKeySpec keySpec = new PBEKeySpec(PASSWORD);
SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE");
SecretKey skey = skFac.generateSecret(keySpec);
Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede");
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
// Pre-calculated keys and certs and aliases
byte[][] keys = new byte[SIZE][];
Certificate[][] certChains = new Certificate[SIZE][];
String[] aliases = new String[SIZE];
// Reads from JKS keystore and pre-calculate
KeyStore ks = KeyStore.getInstance("jks");
try (FileInputStream fis = new FileInputStream(JKSFILE)) {
ks.load(fis, PASSWORD);
}
for (int i = 0; i < SIZE; i++) {
aliases[i] = "p" + i;
byte[] enckey = cipher.doFinal(ks.getKey(aliases[i], PASSWORD).getEncoded());
keys[i] = new EncryptedPrivateKeyInfo(algid, enckey).getEncoded();
certChains[i] = ks.getCertificateChain(aliases[i]);
}
// Write into PKCS12 keystore. Use this overloaded version of
// setKeyEntry() to be as fast as possible, so that they would
// have same localKeyId.
KeyStore p12 = KeyStore.getInstance("pkcs12");
p12.load(null, PASSWORD);
for (int i = 0; i < SIZE; i++) {
p12.setKeyEntry(aliases[i], keys[i], certChains[i]);
}
try (FileOutputStream fos = new FileOutputStream(P12FILE)) {
p12.store(fos, PASSWORD);
}
// Check private keys still match certs
p12 = KeyStore.getInstance("pkcs12");
try (FileInputStream fis = new FileInputStream(P12FILE)) {
p12.load(fis, PASSWORD);
}
for (int i = 0; i < SIZE; i++) {
String a = "p" + i;
X509Certificate x = (X509Certificate) p12.getCertificate(a);
X500Name name = (X500Name) x.getSubjectDN();
if (!name.getCommonName().equals("" + i)) {
throw new Exception(a + "'s cert is " + name);
}
}
}
use of sun.security.pkcs.EncryptedPrivateKeyInfo in project Bytecoder by mirkosertic.
the class PKCS12KeyStore method encryptPrivateKey.
/*
* Encrypt private key using Password-based encryption (PBE)
* as defined in PKCS#5.
*
* NOTE: By default, pbeWithSHAAnd3-KeyTripleDES-CBC algorithmID is
* used to derive the key and IV.
*
* @return encrypted private key encoded as EncryptedPrivateKeyInfo
*/
private byte[] encryptPrivateKey(byte[] data, KeyStore.PasswordProtection passwordProtection) throws IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
byte[] key = null;
try {
String algorithm;
AlgorithmParameters algParams;
AlgorithmId algid;
// Initialize PBE algorithm and parameters
algorithm = passwordProtection.getProtectionAlgorithm();
if (algorithm != null) {
AlgorithmParameterSpec algParamSpec = passwordProtection.getProtectionParameters();
if (algParamSpec != null) {
algParams = AlgorithmParameters.getInstance(algorithm);
algParams.init(algParamSpec);
} else {
algParams = getAlgorithmParameters(algorithm);
}
} else {
// Check default key protection algorithm for PKCS12 keystores
algorithm = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
String prop = Security.getProperty(KEY_PROTECTION_ALGORITHM[0]);
if (prop == null) {
prop = Security.getProperty(KEY_PROTECTION_ALGORITHM[1]);
}
return prop;
}
});
if (algorithm == null || algorithm.isEmpty()) {
algorithm = "PBEWithSHA1AndDESede";
}
algParams = getAlgorithmParameters(algorithm);
}
ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm);
if (pbeOID == null) {
throw new IOException("PBE algorithm '" + algorithm + " 'is not supported for key entry protection");
}
// Use JCE
SecretKey skey = getPBEKey(passwordProtection.getPassword());
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skey, algParams);
byte[] encryptedKey = cipher.doFinal(data);
algid = new AlgorithmId(pbeOID, cipher.getParameters());
if (debug != null) {
debug.println(" (Cipher algorithm: " + cipher.getAlgorithm() + ")");
}
// wrap encrypted private key in EncryptedPrivateKeyInfo
// as defined in PKCS#8
EncryptedPrivateKeyInfo encrInfo = new EncryptedPrivateKeyInfo(algid, encryptedKey);
key = encrInfo.getEncoded();
} catch (Exception e) {
UnrecoverableKeyException uke = new UnrecoverableKeyException("Encrypt Private Key failed: " + e.getMessage());
uke.initCause(e);
throw uke;
}
return key;
}
use of sun.security.pkcs.EncryptedPrivateKeyInfo in project Bytecoder by mirkosertic.
the class PKCS12KeyStore method createSafeContent.
/*
* Create SafeContent Data content type.
* Includes encrypted secret key in a SafeBag of type SecretBag.
* Includes encrypted private key in a SafeBag of type PKCS8ShroudedKeyBag.
* Each PKCS8ShroudedKeyBag includes pkcs12 attributes
* (see comments in getBagAttributes)
*/
private byte[] createSafeContent() throws CertificateException, IOException {
DerOutputStream out = new DerOutputStream();
for (Enumeration<String> e = engineAliases(); e.hasMoreElements(); ) {
String alias = e.nextElement();
Entry entry = entries.get(alias);
if (entry == null || (!(entry instanceof KeyEntry))) {
continue;
}
DerOutputStream safeBag = new DerOutputStream();
KeyEntry keyEntry = (KeyEntry) entry;
// DER encode the private key
if (keyEntry instanceof PrivateKeyEntry) {
// Create SafeBag of type pkcs8ShroudedKeyBag
safeBag.putOID(PKCS8ShroudedKeyBag_OID);
// get the encrypted private key
byte[] encrBytes = ((PrivateKeyEntry) keyEntry).protectedPrivKey;
EncryptedPrivateKeyInfo encrInfo = null;
try {
encrInfo = new EncryptedPrivateKeyInfo(encrBytes);
} catch (IOException ioe) {
throw new IOException("Private key not stored as " + "PKCS#8 EncryptedPrivateKeyInfo" + ioe.getMessage());
}
// Wrap the EncryptedPrivateKeyInfo in a context-specific tag.
DerOutputStream bagValue = new DerOutputStream();
bagValue.write(encrInfo.getEncoded());
safeBag.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), bagValue);
// DER encode the secret key
} else if (keyEntry instanceof SecretKeyEntry) {
// Create SafeBag of type SecretBag
safeBag.putOID(SecretBag_OID);
// Create a SecretBag
DerOutputStream secretBag = new DerOutputStream();
secretBag.putOID(PKCS8ShroudedKeyBag_OID);
// Write secret key in a context-specific tag
DerOutputStream secretKeyValue = new DerOutputStream();
secretKeyValue.putOctetString(((SecretKeyEntry) keyEntry).protectedSecretKey);
secretBag.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), secretKeyValue);
// Wrap SecretBag in a Sequence
DerOutputStream secretBagSeq = new DerOutputStream();
secretBagSeq.write(DerValue.tag_Sequence, secretBag);
byte[] secretBagValue = secretBagSeq.toByteArray();
// Wrap the secret bag in a context-specific tag.
DerOutputStream bagValue = new DerOutputStream();
bagValue.write(secretBagValue);
// Write SafeBag value
safeBag.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), bagValue);
} else {
// skip this entry
continue;
}
// write SafeBag Attributes
byte[] bagAttrs = getBagAttributes(alias, entry.keyId, entry.attributes);
safeBag.write(bagAttrs);
// wrap as Sequence
out.write(DerValue.tag_Sequence, safeBag);
}
// wrap as Sequence
DerOutputStream safeBagValue = new DerOutputStream();
safeBagValue.write(DerValue.tag_Sequence, out);
return safeBagValue.toByteArray();
}
Aggregations