diff options
Diffstat (limited to 'crypto/src/openpgp/PgpSecretKey.cs')
-rw-r--r-- | crypto/src/openpgp/PgpSecretKey.cs | 78 |
1 files changed, 57 insertions, 21 deletions
diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs index 94c892a87..872316dd7 100644 --- a/crypto/src/openpgp/PgpSecretKey.cs +++ b/crypto/src/openpgp/PgpSecretKey.cs @@ -5,6 +5,7 @@ using System.IO; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Bcpg.OpenPgp { @@ -75,28 +76,36 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp pOut.WriteObject(secKey); byte[] keyData = bOut.ToArray(); - byte[] checksumBytes = Checksum(useSha1, keyData, keyData.Length); + byte[] checksumData = Checksum(useSha1, keyData, keyData.Length); - pOut.Write(checksumBytes); - - byte[] bOutData = bOut.ToArray(); + keyData = Arrays.Concatenate(keyData, checksumData); if (encAlgorithm == SymmetricKeyAlgorithmTag.Null) { if (isMasterKey) { - this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData); + this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, keyData); } else { - this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, bOutData); + this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, keyData); } } else { S2k s2k; byte[] iv; - byte[] encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2k, out iv); + + byte[] encData; + if (pub.Version >= 4) + { + encData = EncryptKeyData(keyData, encAlgorithm, passPhrase, rand, out s2k, out iv); + } + else + { + // TODO v3 RSA key encryption + throw Platform.CreateNotImplementedException("v3 RSA"); + } int s2kUsage = useSha1 ? SecretKeyPacket.UsageSha1 @@ -145,11 +154,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand) - : this(keyPair.PrivateKey, certifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, passPhrase, useSha1, rand, true) + : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, passPhrase, useSha1, rand, true) { } - private static PgpPublicKey certifiedPublicKey( + private static PgpPublicKey CertifiedPublicKey( int certificationLevel, PgpKeyPair keyPair, string id, @@ -254,6 +263,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp get { return pub.IsMasterKey; } } + /// <summary>Detect if the Secret Key's Private Key is empty or not</summary> + public bool IsPrivateKeyEmpty + { + get + { + byte[] secKeyData = secret.GetSecretKeyData(); + + return secKeyData == null || secKeyData.Length < 1; + } + } + /// <summary>The algorithm the key is encrypted with.</summary> public SymmetricKeyAlgorithmTag KeyEncryptionAlgorithm { @@ -293,9 +313,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp byte[] encData = secret.GetSecretKeyData(); if (alg == SymmetricKeyAlgorithmTag.Null) + // TODO Check checksum here? return encData; - byte[] data; IBufferedCipher c = null; try { @@ -307,13 +327,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp throw new PgpException("Exception creating cipher", e); } - // TODO Factor this block out as 'encryptData' + // TODO Factor this block out as 'decryptData' try { KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase); byte[] iv = secret.GetIV(); + byte[] data; - if (secret.PublicKeyPacket.Version == 4) + if (secret.PublicKeyPacket.Version >= 4) { c.Init(false, new ParametersWithIV(key, iv)); @@ -334,6 +355,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { data = new byte[encData.Length]; + iv = Arrays.Clone(iv); + // // read in the four numbers // @@ -359,11 +382,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } // - // verify Checksum + // verify and copy checksum // + + data[pos] = encData[pos]; + data[pos + 1] = encData[pos + 1]; + int cs = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff); int calcCs = 0; - for (int j=0; j < data.Length-2; j++) + for (int j = 0; j < pos; j++) { calcCs += data[j] & 0xff; } @@ -393,8 +420,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp public PgpPrivateKey ExtractPrivateKey( char[] passPhrase) { - byte[] secKeyData = secret.GetSecretKeyData(); - if (secKeyData == null || secKeyData.Length < 1) + if (IsPrivateKeyEmpty) return null; PublicKeyPacket pubPk = secret.PublicKeyPacket; @@ -559,11 +585,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand) { + if (key.IsPrivateKeyEmpty) + throw new PgpException("no private key in this SecretKey - public key present only."); + byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase); int s2kUsage = key.secret.S2kUsage; byte[] iv = null; S2k s2k = null; byte[] keyData; + PublicKeyPacket pubKeyPacket = key.secret.PublicKeyPacket; if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null) { @@ -588,7 +618,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { try { - keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv); + if (pubKeyPacket.Version >= 4) + { + keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv); + } + else + { + // TODO v3 RSA key encryption + throw Platform.CreateNotImplementedException("v3 RSA"); + } } catch (PgpException e) { @@ -603,13 +641,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp SecretKeyPacket secret; if (key.secret is SecretSubkeyPacket) { - secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket, - newEncAlgorithm, s2kUsage, s2k, iv, keyData); + secret = new SecretSubkeyPacket(pubKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } else { - secret = new SecretKeyPacket(key.secret.PublicKeyPacket, - newEncAlgorithm, s2kUsage, s2k, iv, keyData); + secret = new SecretKeyPacket(pubKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } return new PgpSecretKey(secret, key.pub); |