use of org.kse.crypto.CryptoException in project keystore-explorer by kaikramer.
the class MsPvkUtil method loadEncrypted.
/**
* Load an encrypted PVK private key from the specified stream.
*
* @param is
* Stream load the encrypted private key from
* @param password
* Password to decrypt
* @return The private key
* @throws PrivateKeyUnencryptedException
* If private key is unencrypted
* @throws CryptoException
* Problem encountered while loading the private key
* @throws IOException
* An I/O error occurred
*/
public static PrivateKey loadEncrypted(InputStream is, Password password) throws IOException, CryptoException {
try {
byte[] pvk = ReadUtil.readFully(is);
// Wrap in a byte buffer set up to read little endian
ByteBuffer bb = ByteBuffer.wrap(pvk);
bb.order(ByteOrder.LITTLE_ENDIAN);
// Read and validate the reserved, magic number and key type fields - only returns the latter
long keyType = readReservedMagicKeyType(bb);
// Read and validate encrypted field
long encrypted = UnsignedUtil.getInt(bb);
if (encrypted != PVK_ENCRYPTED) {
throw new PrivateKeyUnencryptedException(MessageFormat.format(res.getString("MsPvkIsUnencrypted.exception.message"), Long.toHexString(encrypted), Long.toHexString(PVK_ENCRYPTED)));
}
// Read and validate salt length field
long saltLength = UnsignedUtil.getInt(bb);
if (saltLength != ENCRYPTED_SALT_LENGTH) {
// Specific length for encrypted PVK
throw new CryptoException(MessageFormat.format(res.getString("InvalidMsPvkSaltLengthField.exception.message"), Long.toHexString(saltLength), Long.toHexString(ENCRYPTED_SALT_LENGTH)));
}
// Read key length
long keyLength = UnsignedUtil.getInt(bb);
// Create decryption keys
// Strong version
byte[] strongKey = new byte[16];
// Weak version
byte[] weakKey = new byte[16];
// Read Salt
byte[] salt = new byte[(int) saltLength];
bb.get(salt);
// Concatenate salt and password and derive key using SHA-1
MessageDigest messagedigest = MessageDigest.getInstance("SHA1");
byte[] passwordBytes = new String(password.toCharArray()).getBytes();
byte[] saltAndPassword = new byte[salt.length + passwordBytes.length];
System.arraycopy(salt, 0, saltAndPassword, 0, salt.length);
System.arraycopy(passwordBytes, 0, saltAndPassword, salt.length, passwordBytes.length);
byte[] key = messagedigest.digest(saltAndPassword);
// Create strong key - first 16 bytes of key
System.arraycopy(key, 0, strongKey, 0, 16);
// Create weak key - first 5 bytes of key followed by 11 zero bytes
System.arraycopy(key, 0, weakKey, 0, 5);
for (int i = 5; i < 16; i++) {
weakKey[i] = 0;
}
// Read private key blob header
readPrivateKeyBlobHeader(bb, keyType);
// Read all remaining bytes - the encrypted key
byte[] encryptedPrivateKeyBlob = new byte[bb.remaining()];
bb.get(encryptedPrivateKeyBlob);
// Validate key length - should be length of encrypted key blob plus blob header
if (keyLength != (encryptedPrivateKeyBlob.length + BLOB_HEADER_LENGTH)) {
throw new CryptoException(MessageFormat.format(res.getString("InvalidMsPvkKeyLengthField.exception.message"), Long.toHexString(keyLength), Long.toHexString(encryptedPrivateKeyBlob.length + BLOB_HEADER_LENGTH)));
}
// Decrypt key using RC4 with strong key
byte[] decryptedPrivateKeyBlob = decryptPrivateKeyBlob(encryptedPrivateKeyBlob, strongKey);
// Test for success
if (decryptedPrivateKeyBlob == null) {
// Failed - now try weak key
decryptedPrivateKeyBlob = decryptPrivateKeyBlob(encryptedPrivateKeyBlob, weakKey);
if (decryptedPrivateKeyBlob == null) {
// Failed - could not decrypt - password is most likely incorrect
throw new CryptoException(res.getString("NoDecryptMsPvkCheckPassword.exception.message"));
}
}
return blobToPrivateKey(decryptedPrivateKeyBlob);
} catch (GeneralSecurityException ex) {
throw new CryptoException(res.getString("NoLoadMsPvk.exception.message"), ex);
}
}
use of org.kse.crypto.CryptoException in project keystore-explorer by kaikramer.
the class MsPvkUtil method getEncryptedInternal.
private static byte[] getEncryptedInternal(PrivateKey privateKey, int keyType, Password password, boolean strong) throws CryptoException {
try {
// Write PVK to a byte buffer set up to write little endian
ByteBuffer bb = ByteBuffer.wrap(new byte[PVK_BUFFER_LENGTH]);
bb.order(ByteOrder.LITTLE_ENDIAN);
// Write magic number, reserved and and key type fields
writeReservedMagicKeyType(bb, keyType);
// Get password as bytes
byte[] passwordBytes = new String(password.toCharArray()).getBytes();
// Generate salt for encryption
byte[] salt = generate16ByteSalt();
// Concatenate the salt and password
byte[] saltAndPassword = new byte[salt.length + passwordBytes.length];
System.arraycopy(salt, 0, saltAndPassword, 0, salt.length);
System.arraycopy(passwordBytes, 0, saltAndPassword, salt.length, passwordBytes.length);
// Digest the salt and password to create the encryption key
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
byte[] key = messageDigest.digest(saltAndPassword);
// Get private key blob
byte[] privateKeyBlob = null;
if (privateKey instanceof RSAPrivateCrtKey) {
privateKeyBlob = rsaPrivateKeyToBlob((RSAPrivateCrtKey) privateKey);
} else {
privateKeyBlob = dsaPrivateKeyToBlob((DSAPrivateKey) privateKey);
}
// Encrypt private key blob
byte[] encryptedPrivateKeyBlob = null;
if (strong) {
// Strong version uses all 16 bytes of the key
byte[] strongKey = new byte[16];
System.arraycopy(key, 0, strongKey, 0, strongKey.length);
encryptedPrivateKeyBlob = encryptPrivateKeyBlob(privateKeyBlob, strongKey);
} else {
// The weak version uses only 5 bytes of the key followed by 11 zero bytes
byte[] weakKey = new byte[16];
System.arraycopy(key, 0, weakKey, 0, 5);
for (int i = 5; i < weakKey.length; i++) {
weakKey[i] = 0;
}
encryptedPrivateKeyBlob = encryptPrivateKeyBlob(privateKeyBlob, weakKey);
}
// Write type field - encrypted
UnsignedUtil.putInt(bb, PVK_ENCRYPTED);
// Write salt length field
UnsignedUtil.putInt(bb, salt.length);
// Write key length field - length of the blob plus length blob header
int keyLength = encryptedPrivateKeyBlob.length + BLOB_HEADER_LENGTH;
UnsignedUtil.putInt(bb, keyLength);
// Write salt
bb.put(salt);
// Write private key blob header
writePrivateKeyBlobHeader(bb, keyType, privateKey);
// Write blob
bb.put(encryptedPrivateKeyBlob);
byte[] encryptedPvk = getBufferBytes(bb);
return encryptedPvk;
} catch (IOException ex) {
throw new CryptoException(res.getString("NoGetMsPvk.exception.message"), ex);
} catch (NoSuchAlgorithmException ex) {
throw new CryptoException(res.getString("NoGetMsPvk.exception.message"), ex);
}
}
use of org.kse.crypto.CryptoException in project keystore-explorer by kaikramer.
the class MsPvkUtil method rsaPrivateKeyToBlob.
private static byte[] rsaPrivateKeyToBlob(RSAPrivateCrtKey rsaPrivCrtKey) throws CryptoException {
try {
// 2316 sufficient for a 4096 bit RSA key
ByteBuffer bb = ByteBuffer.wrap(new byte[4096]);
bb.order(ByteOrder.LITTLE_ENDIAN);
// Write out the blob fields
// rsapubkey.magic
UnsignedUtil.putInt(bb, RSA_PRIV_MAGIC);
BigInteger modulus = rsaPrivCrtKey.getModulus();
int bitLength = modulus.bitLength();
// rsapubkey.bitlen
UnsignedUtil.putInt(bb, bitLength);
BigInteger publicExponent = rsaPrivCrtKey.getPublicExponent();
// rsapubkey.pubexp
UnsignedUtil.putInt(bb, (int) publicExponent.longValue());
/*
* Byte lengths divisions may have remainders to take account for if
* not factors of 16 and/or 8
*/
int add8 = 0;
if ((bitLength % 8) != 0) {
add8++;
}
int add16 = 0;
if ((bitLength % 16) != 0) {
add16++;
}
// modulus
writeBigInteger(bb, modulus, (bitLength / 8) + add8);
// prime1
writeBigInteger(bb, rsaPrivCrtKey.getPrimeP(), (bitLength / 16) + add16);
// prime2
writeBigInteger(bb, rsaPrivCrtKey.getPrimeQ(), (bitLength / 16) + add16);
// exponent1
writeBigInteger(bb, rsaPrivCrtKey.getPrimeExponentP(), (bitLength / 16) + add16);
// exponent2
writeBigInteger(bb, rsaPrivCrtKey.getPrimeExponentQ(), (bitLength / 16) + add16);
// coefficient
writeBigInteger(bb, rsaPrivCrtKey.getCrtCoefficient(), (bitLength / 16) + add16);
// privateExponent
writeBigInteger(bb, rsaPrivCrtKey.getPrivateExponent(), (bitLength / 8) + add8);
return getBufferBytes(bb);
} catch (IOException ex) {
throw new CryptoException(res.getString("NoConvertKeyToBlob.exception.message"), ex);
}
}
use of org.kse.crypto.CryptoException in project keystore-explorer by kaikramer.
the class MsPvkUtil method dsaPrivateKeyToBlob.
private static byte[] dsaPrivateKeyToBlob(DSAPrivateKey dsaPrivKey) throws CryptoException {
try {
DSAParams dsaParams = dsaPrivKey.getParams();
// 328 sufficient for a 1024 bit DSA key
ByteBuffer bb = ByteBuffer.wrap(new byte[512]);
bb.order(ByteOrder.LITTLE_ENDIAN);
// Write out the blob fields
// dsspubkey.magic
UnsignedUtil.putInt(bb, DSS_PRIV_MAGIC);
BigInteger prime = dsaParams.getP();
int bitLength = prime.toString(2).length();
// dsspubkey.bitlen
UnsignedUtil.putInt(bb, bitLength);
/*
* Unlike RSA there are no bit length remainders (ie DSA bit length
* always divisible by 8 as they are multiples of 64)
*/
// modulus
writeBigInteger(bb, dsaParams.getP(), (bitLength / 8));
// prime
writeBigInteger(bb, dsaParams.getQ(), 20);
// generator
writeBigInteger(bb, dsaParams.getG(), (bitLength / 8));
// secret exponent
writeBigInteger(bb, dsaPrivKey.getX(), 20);
// dssseed.counter - none, fill 0xff
UnsignedUtil.putInt(bb, 0xffffffff);
for (// dssseed.seed - none, fill 0xff
int i = 0; // dssseed.seed - none, fill 0xff
i < 20; // dssseed.seed - none, fill 0xff
i++) {
bb.put((byte) 0xff);
}
return getBufferBytes(bb);
} catch (IOException ex) {
throw new CryptoException(res.getString("NoConvertKeyToBlob.exception.message"), ex);
}
}
use of org.kse.crypto.CryptoException in project keystore-explorer by kaikramer.
the class MsPvkUtil method encryptPrivateKeyBlob.
private static byte[] encryptPrivateKeyBlob(byte[] privateKeyBlob, byte[] rc4Key) throws CryptoException {
try {
SecretKeySpec rc4KeySpec = new SecretKeySpec(rc4Key, "RC4");
Cipher rc42 = Cipher.getInstance("RC4");
rc42.init(Cipher.ENCRYPT_MODE, rc4KeySpec);
return rc42.doFinal(privateKeyBlob);
} catch (GeneralSecurityException ex) {
throw new CryptoException(res.getString("PrivateKeyBlobRc4EncryptionFailed.exception.message"), ex);
}
}
Aggregations