diff options
Diffstat (limited to 'crypto/src/openpgp/PgpSecretKey.cs')
-rw-r--r-- | crypto/src/openpgp/PgpSecretKey.cs | 112 |
1 files changed, 95 insertions, 17 deletions
diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs index 0f472c1a4..d3811c44c 100644 --- a/crypto/src/openpgp/PgpSecretKey.cs +++ b/crypto/src/openpgp/PgpSecretKey.cs @@ -97,12 +97,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp byte[] encData; if (pub.Version >= 4) { - encData = EncryptKeyData(keyData, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv); + encData = EncryptKeyDataV4(keyData, encAlgorithm, HashAlgorithmTag.Sha1, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv); } else { - // TODO v3 RSA key encryption - throw Platform.CreateNotImplementedException("v3 RSA"); + encData = EncryptKeyDataV3(keyData, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv); } int s2kUsage = useSha1 @@ -461,6 +460,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp get { return pub.KeyId; } } + /// <summary>Return the S2K usage associated with this key.</summary> + public int S2kUsage + { + get { return secret.S2kUsage; } + } + + /// <summary>Return the S2K used to process this key.</summary> + public S2k S2k + { + get { return secret.S2k; } + } + /// <summary>The public key associated with this key.</summary> public PgpPublicKey PublicKey { @@ -904,12 +915,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { if (pubKeyPacket.Version >= 4) { - keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv); + keyData = EncryptKeyDataV4(rawKeyData, newEncAlgorithm, HashAlgorithmTag.Sha1, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv); } else { - // TODO v3 RSA key encryption - throw Platform.CreateNotImplementedException("v3 RSA"); + keyData = EncryptKeyDataV3(rawKeyData, newEncAlgorithm, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv); } } catch (PgpException e) @@ -950,7 +960,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return new PgpSecretKey(secretKey.secret, publicKey); } - private static byte[] EncryptKeyData( + private static byte[] EncryptKeyDataV3( byte[] rawKeyData, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, @@ -959,6 +969,78 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp out S2k s2k, out byte[] iv) { + // Version 2 or 3 - RSA Keys only + + s2k = null; + iv = null; + + KeyParameter encKey = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase); + + byte[] keyData = new byte[rawKeyData.Length]; + + // + // process 4 numbers + // + int pos = 0; + for (int i = 0; i != 4; i++) + { + int encLen = (((rawKeyData[pos] << 8) | (rawKeyData[pos + 1] & 0xff)) + 7) / 8; + + keyData[pos] = rawKeyData[pos]; + keyData[pos + 1] = rawKeyData[pos + 1]; + + byte[] tmp; + if (i == 0) + { + tmp = EncryptData(encAlgorithm, encKey, rawKeyData, pos + 2, encLen, random, ref iv); + } + else + { + byte[] tmpIv = Arrays.CopyOfRange(keyData, pos - iv.Length, pos); + + tmp = EncryptData(encAlgorithm, encKey, rawKeyData, pos + 2, encLen, random, ref tmpIv); + } + + Array.Copy(tmp, 0, keyData, pos + 2, tmp.Length); + pos += 2 + encLen; + } + + // + // copy in checksum. + // + keyData[pos] = rawKeyData[pos]; + keyData[pos + 1] = rawKeyData[pos + 1]; + + return keyData; + } + + private static byte[] EncryptKeyDataV4( + byte[] rawKeyData, + SymmetricKeyAlgorithmTag encAlgorithm, + HashAlgorithmTag hashAlgorithm, + byte[] rawPassPhrase, + bool clearPassPhrase, + SecureRandom random, + out S2k s2k, + out byte[] iv) + { + s2k = PgpUtilities.GenerateS2k(hashAlgorithm, 0x60, random); + + KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase); + + iv = null; + return EncryptData(encAlgorithm, key, rawKeyData, 0, rawKeyData.Length, random, ref iv); + } + + private static byte[] EncryptData( + SymmetricKeyAlgorithmTag encAlgorithm, + KeyParameter key, + byte[] data, + int dataOff, + int dataLen, + SecureRandom random, + ref byte[] iv) + { IBufferedCipher c; try { @@ -970,18 +1052,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp throw new PgpException("Exception creating cipher", e); } - byte[] s2kIV = new byte[8]; - random.NextBytes(s2kIV); - s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60); - - KeyParameter kp = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase); - - iv = new byte[c.GetBlockSize()]; - random.NextBytes(iv); + if (iv == null) + { + iv = PgpUtilities.GenerateIV(c.GetBlockSize(), random); + } - c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random)); + c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), random)); - return c.DoFinal(rawKeyData); + return c.DoFinal(data, dataOff, dataLen); } /// <summary> |