internal PbeMethod( SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, KeyParameter key) { this.encAlgorithm = encAlgorithm; this.s2k = s2k; this.key = key; }
private static byte[] EncryptKeyDataV3( byte[] rawKeyData, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, SecureRandom random, 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; }
/// <remarks> /// Allows the caller to handle the encoding of the passphrase to bytes. /// </remarks> public static KeyParameter MakeKeyFromPassPhraseRaw(SymmetricKeyAlgorithmTag algorithm, S2k s2k, byte[] rawPassPhrase) { return DoMakeKeyFromPassPhrase(algorithm, s2k, rawPassPhrase, false); }
/// <summary> /// Initializes a new instance of the <see cref="SecretSubkeyPacket"/> class. /// </summary> /// <param name="pubKeyPacket">The pub key packet.</param> /// <param name="encAlgorithm">The enc algorithm.</param> /// <param name="s2KUsage">The s2 K usage.</param> /// <param name="s2K">The s2 K.</param> /// <param name="iv">The iv.</param> /// <param name="secKeyData">The sec key data.</param> public SecretSubkeyPacket(IPublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, int s2KUsage, S2k s2K, byte[] iv, byte[] secKeyData) : base(pubKeyPacket, encAlgorithm, s2KUsage, s2K, iv, secKeyData) { }
/// <remarks> /// Allows the caller to handle the encoding of the passphrase to bytes. /// </remarks> public static KeyParameter MakeKeyFromPassPhraseRaw(SymmetricKeyAlgorithmTag algorithm, S2k s2k, byte[] rawPassPhrase) { return(DoMakeKeyFromPassPhrase(algorithm, s2k, rawPassPhrase, false)); }
internal void DoAddMethod(byte[] rawPassPhrase, bool clearPassPhrase, HashAlgorithmTag s2kDigest) { S2k s2k = PgpUtilities.GenerateS2k(s2kDigest, 0x60, rand); methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.DoMakeKeyFromPassPhrase(defAlgorithm, s2k, rawPassPhrase, clearPassPhrase))); }
public SecretKeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, byte[] iv, byte[] secKeyData) { this.pubKeyPacket = pubKeyPacket; this.encAlgorithm = encAlgorithm; if (encAlgorithm != 0) { s2kUsage = 255; } else { s2kUsage = 0; } this.s2k = s2k; this.iv = Arrays.Clone(iv); this.secKeyData = secKeyData; }
internal static KeyParameter DoMakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag algorithm, S2k s2k, byte[] rawPassPhrase, bool clearPassPhrase) { int keySize = GetKeySize(algorithm); byte[] array = new byte[(keySize + 7) / 8]; int num = 0; int num2 = 0; while (num < array.Length) { IDigest digest; if (s2k != null) { string digestName = GetDigestName(s2k.HashAlgorithm); try { digest = DigestUtilities.GetDigest(digestName); } catch (global::System.Exception exception) { throw new PgpException("can't find S2k digest", exception); } for (int i = 0; i != num2; i++) { digest.Update(0); } byte[] iV = s2k.GetIV(); switch (s2k.Type) { case 0: digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length); break; case 1: digest.BlockUpdate(iV, 0, iV.Length); digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length); break; case 3: { long iterationCount = s2k.IterationCount; digest.BlockUpdate(iV, 0, iV.Length); digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length); iterationCount -= iV.Length + rawPassPhrase.Length; while (iterationCount > 0) { if (iterationCount < iV.Length) { digest.BlockUpdate(iV, 0, (int)iterationCount); break; } digest.BlockUpdate(iV, 0, iV.Length); iterationCount -= iV.Length; if (iterationCount < rawPassPhrase.Length) { digest.BlockUpdate(rawPassPhrase, 0, (int)iterationCount); iterationCount = 0L; } else { digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length); iterationCount -= rawPassPhrase.Length; } } break; } default: throw new PgpException(string.Concat((object)"unknown S2k type: ", (object)s2k.Type)); } } else { try { digest = DigestUtilities.GetDigest("MD5"); for (int j = 0; j != num2; j++) { digest.Update(0); } digest.BlockUpdate(rawPassPhrase, 0, rawPassPhrase.Length); } catch (global::System.Exception exception2) { throw new PgpException("can't find MD5 digest", exception2); } } byte[] array2 = DigestUtilities.DoFinal(digest); if (array2.Length > array.Length - num) { global::System.Array.Copy((global::System.Array)array2, 0, (global::System.Array)array, num, array.Length - num); } else { global::System.Array.Copy((global::System.Array)array2, 0, (global::System.Array)array, num, array2.Length); } num += array2.Length; num2++; } if (clearPassPhrase && rawPassPhrase != null) { global::System.Array.Clear((global::System.Array)rawPassPhrase, 0, rawPassPhrase.Length); } return(MakeKey(algorithm, array)); }
internal PbeMethod( PgpEncryptedDataGenerator outer, SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, KeyParameter key) { this.outer = outer; this.encAlgorithm = encAlgorithm; this.s2k = s2k; this.key = key; }
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, 96, 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[] EncryptKeyDataV3(byte[] rawKeyData, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, SecureRandom random, out S2k s2k, out byte[] iv) { s2k = null; iv = null; KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase); byte[] array = new byte[rawKeyData.Length]; int num = 0; for (int i = 0; i != 4; i++) { int num2 = (((rawKeyData[num] << 8) | (rawKeyData[num + 1] & 0xFF)) + 7) / 8; array[num] = rawKeyData[num]; array[num + 1] = rawKeyData[num + 1]; byte[] array2; if (i == 0) { array2 = EncryptData(encAlgorithm, key, rawKeyData, num + 2, num2, random, ref iv); } else { byte[] iv2 = Arrays.CopyOfRange(array, num - iv.Length, num); array2 = EncryptData(encAlgorithm, key, rawKeyData, num + 2, num2, random, ref iv2); } global::System.Array.Copy((global::System.Array)array2, 0, (global::System.Array)array, num + 2, array2.Length); num += 2 + num2; } array[num] = rawKeyData[num]; array[num + 1] = rawKeyData[num + 1]; return(array); }
internal PbeMethod(SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, KeyParameter key) { base.encAlgorithm = encAlgorithm; this.s2k = s2k; base.key = key; }
public SecretKeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, int s2kUsage, S2k s2k, byte[] iv, byte[] secKeyData) { this.pubKeyPacket = pubKeyPacket; this.encAlgorithm = encAlgorithm; this.s2kUsage = s2kUsage; this.s2k = s2k; this.iv = Arrays.Clone(iv); this.secKeyData = secKeyData; }
/// <summary> /// Return a copy of the passed in secret key, encrypted using a new password /// and the passed in algorithm. /// </summary> /// <param name="key">The PgpSecretKey to be copied.</param> /// <param name="oldPassPhrase">The current password for the key.</param> /// <param name="newPassPhrase">The new password for the key.</param> /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param> /// <param name="rand">Source of randomness.</param> public static PgpSecretKey CopyWithNewPassword( PgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, 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) { s2kUsage = SecretKeyPacket.UsageNone; if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite Checksum { keyData = new byte[rawKeyData.Length - 18]; Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2); byte[] check = Checksum(false, keyData, keyData.Length - 2); keyData[keyData.Length - 2] = check[0]; keyData[keyData.Length - 1] = check[1]; } else { keyData = rawKeyData; } } else { try { 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) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } } SecretKeyPacket secret; if (key.secret is SecretSubkeyPacket) { secret = new SecretSubkeyPacket(pubKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } else { secret = new SecretKeyPacket(pubKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } return(new PgpSecretKey(secret, key.pub)); }
private static byte[] EncryptKeyData( byte[] rawKeyData, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, ISecureRandom random, out S2k s2K, out byte[] iv) { IBufferedCipher c; try { var cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm); c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } var s2KIv = new byte[8]; random.NextBytes(s2KIv); s2K = new S2k(HashAlgorithmTag.Sha1, s2KIv, 0x60); var kp = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2K, passPhrase); iv = new byte[c.GetBlockSize()]; random.NextBytes(iv); c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random)); return c.DoFinal(rawKeyData); }
internal PgpSecretKey( PgpKeyPair keyPair, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSHA1, SecureRandom rand) { PublicKeyPacket pubPk = keyPair.PublicKey.publicPk; BcpgObject secKey; switch (keyPair.PublicKey.Algorithm) { case PublicKeyAlgorithmTag.RsaEncrypt: case PublicKeyAlgorithmTag.RsaSign: case PublicKeyAlgorithmTag.RsaGeneral: RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters)keyPair.PrivateKey.Key; secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q); break; case PublicKeyAlgorithmTag.Dsa: DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters)keyPair.PrivateKey.Key; secKey = new DsaSecretBcpgKey(dsK.X); break; case PublicKeyAlgorithmTag.ElGamalEncrypt: case PublicKeyAlgorithmTag.ElGamalGeneral: ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters)keyPair.PrivateKey.Key; secKey = new ElGamalSecretBcpgKey(esK.X); break; default: throw new PgpException("unknown key class"); } string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm); IBufferedCipher c = null; if (cName != null) { try { c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } } try { MemoryStream bOut = new MemoryStream(); BcpgOutputStream pOut = new BcpgOutputStream(bOut); pOut.WriteObject(secKey); byte[] keyData = bOut.ToArray(); byte[] checksumBytes = Checksum(useSHA1, keyData, keyData.Length); pOut.Write(checksumBytes); byte[] bOutData = bOut.ToArray(); if (c != null) { byte[] iv = new byte[8]; rand.NextBytes(iv); S2k s2k = new S2k(HashAlgorithmTag.Sha1, iv, 0x60); KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase); iv = new byte[c.GetBlockSize()]; rand.NextBytes(iv); c.Init(true, new ParametersWithIV(key, iv)); byte[] encData = c.DoFinal(bOutData); int usage = useSHA1 ? SecretKeyPacket.UsageSha1 : SecretKeyPacket.UsageChecksum; this.secret = new SecretKeyPacket(pubPk, encAlgorithm, usage, s2k, iv, encData); } else { this.secret = new SecretKeyPacket(pubPk, encAlgorithm, null, null, bOutData); } this.trust = null; } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } this.keySigs = new ArrayList(); }
public SecretSubkeyPacket(PublicKeyPacket pubKeyPacket, SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, byte[] iv, byte[] secKeyData) : base(pubKeyPacket, encAlgorithm, s2k, iv, secKeyData) { }
/// <summary> /// Return a copy of the passed in secret key, encrypted using a new password /// and the passed in algorithm. /// </summary> /// <param name="key">The PgpSecretKey to be copied.</param> /// <param name="oldPassPhrase">The current password for the key.</param> /// <param name="newPassPhrase">The new password for the key.</param> /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param> /// <param name="rand">Source of randomness.</param> public static PgpSecretKey CopyWithNewPassword( PgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand) { byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase); int s2kUsage = key.secret.S2kUsage; byte[] iv = null; S2k s2k = null; byte[] keyData = null; if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null) { s2kUsage = SecretKeyPacket.UsageNone; if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite Checksum { keyData = new byte[rawKeyData.Length - 18]; Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2); byte[] check = Checksum(false, keyData, keyData.Length - 2); keyData[keyData.Length - 2] = check[0]; keyData[keyData.Length - 1] = check[1]; } else { keyData = rawKeyData; } } else { IBufferedCipher c; try { string cName = PgpUtilities.GetSymmetricCipherName(newEncAlgorithm); c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } iv = new byte[8]; rand.NextBytes(iv); s2k = new S2k(HashAlgorithmTag.Sha1, iv, 0x60); try { KeyParameter sKey = PgpUtilities.MakeKeyFromPassPhrase(newEncAlgorithm, s2k, newPassPhrase); iv = new byte[c.GetBlockSize()]; rand.NextBytes(iv); c.Init(true, new ParametersWithIV(sKey, iv)); keyData = c.DoFinal(rawKeyData); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } } SecretKeyPacket secret; if (key.secret is SecretSubkeyPacket) { secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } else { secret = new SecretKeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } if (key.subSigs == null) { return(new PgpSecretKey(secret, key.trust, key.keySigs, key.ids, key.idTrusts, key.idSigs, key.pub)); } return(new PgpSecretKey(secret, key.trust, key.subSigs, key.pub)); }
/// <summary> /// Return a copy of the passed in secret key, encrypted using a new password /// and the passed in algorithm. /// </summary> /// <param name="key">The PgpSecretKey to be copied.</param> /// <param name="oldPassPhrase">The current password for the key.</param> /// <param name="newPassPhrase">The new password for the key.</param> /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param> /// <param name="rand">Source of randomness.</param> public static PgpSecretKey CopyWithNewPassword( PgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand) { byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase); int s2kUsage = key.secret.S2kUsage; byte[] iv = null; S2k s2k = null; byte[] keyData; if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null) { s2kUsage = SecretKeyPacket.UsageNone; if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite Checksum { keyData = new byte[rawKeyData.Length - 18]; Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2); byte[] check = Checksum(false, keyData, keyData.Length - 2); keyData[keyData.Length - 2] = check[0]; keyData[keyData.Length - 1] = check[1]; } else { keyData = rawKeyData; } } else { try { keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } } SecretKeyPacket secret; if (key.secret is SecretSubkeyPacket) { secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } else { secret = new SecretKeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } return(new PgpSecretKey(secret, key.pub)); }
private static SecretKeyPacket buildSecretKeyPacket(bool isMasterKey, PgpPrivateKey privKey, PgpPublicKey pubKey, IPbeSecretKeyEncryptor keyEncryptor) { BcpgObject secKey = (BcpgObject)privKey.Key; if (secKey == null) { if (isMasterKey) { return(new SecretKeyPacket(pubKey.publicPk, SymmetricKeyAlgorithmTag.Null, null, null, new byte[0])); } else { return(new SecretSubkeyPacket(pubKey.publicPk, SymmetricKeyAlgorithmTag.Null, null, null, new byte[0])); } } try { MemoryOutputStream bOut = new MemoryOutputStream(); BcpgOutputStream pOut = new BcpgOutputStream(bOut); pOut.WriteObject(secKey); byte[] keyData = bOut.ToArray(); byte[] checkData = checksum(keyEncryptor.ChecksumCalculatorFactory, keyData, keyData.Length); pOut.Write(checkData, 0, checkData.Length); PgpPbeKeyEncryptionParameters encParams = keyEncryptor.AlgorithmDetails; SymmetricKeyAlgorithmTag encAlgorithm = (keyEncryptor != null) ? encParams.Algorithm : SymmetricKeyAlgorithmTag.Null; if (encAlgorithm != SymmetricKeyAlgorithmTag.Null) { keyData = bOut.ToArray(); // include checksum byte[] encData = keyEncryptor.Wrap(keyData).Collect(); byte[] iv = encParams.GetIV(); S2k s2k = encParams.S2k; int s2kUsage; if (keyEncryptor.ChecksumCalculatorFactory != null) { if (keyEncryptor.ChecksumCalculatorFactory.AlgorithmDetails.Algorithm != HashAlgorithmTag.Sha1) { throw new PgpException("only SHA1 supported for key checksum calculations."); } s2kUsage = SecretKeyPacket.UsageSha1; } else { s2kUsage = SecretKeyPacket.UsageChecksum; } if (isMasterKey) { return(new SecretKeyPacket(pubKey.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData)); } else { return(new SecretSubkeyPacket(pubKey.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData)); } } else { if (isMasterKey) { return(new SecretKeyPacket(pubKey.publicPk, encAlgorithm, null, null, bOut.ToArray())); } else { return(new SecretSubkeyPacket(pubKey.publicPk, encAlgorithm, null, null, bOut.ToArray())); } } } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } }
/// <remarks> /// The passphrase is encoded to bytes using UTF8 (Encoding.UTF8.GetBytes). /// </remarks> public static KeyParameter MakeKeyFromPassPhraseUtf8(SymmetricKeyAlgorithmTag algorithm, S2k s2k, char[] passPhrase) { return(DoMakeKeyFromPassPhrase(algorithm, s2k, EncodePassPhrase(passPhrase, true), true)); }
/** * Return a copy of the passed in secret key, encrypted using a new * password and the passed in algorithm. * * @param key the PgpSecretKey to be copied. * @param oldKeyDecryptor the current decryptor based on the current password for key. * @param newKeyEncryptor a new encryptor based on a new password for encrypting the secret key material. */ public static PgpSecretKey CopyWithNewPassword( PgpSecretKey key, IPbeSecretKeyDecryptorProvider oldKeyDecryptor, IPbeSecretKeyEncryptor newKeyEncryptor) { if (key.IsPrivateKeyEmpty) { throw new PgpException("no private key in this SecretKey - public key present only."); } byte[] rawKeyData = key.extractKeyData(oldKeyDecryptor); int s2kUsage = key.secret.S2kUsage; byte[] iv = null; S2k s2k = null; byte[] keyData = null; SymmetricKeyAlgorithmTag newEncAlgorithm = SymmetricKeyAlgorithmTag.Null; if (newKeyEncryptor == null || newKeyEncryptor.AlgorithmDetails.Algorithm == SymmetricKeyAlgorithmTag.Null) { s2kUsage = SecretKeyPacket.UsageNone; if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite checksum { keyData = new byte[rawKeyData.Length - 18]; Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2); byte[] check = checksum(null, keyData, keyData.Length - 2); keyData[keyData.Length - 2] = check[0]; keyData[keyData.Length - 1] = check[1]; } else { keyData = rawKeyData; } } else { if (s2kUsage == SecretKeyPacket.UsageNone) { s2kUsage = SecretKeyPacket.UsageChecksum; } if (key.secret.PublicKeyPacket.Version < 4) { // Version 2 or 3 - RSA Keys only keyData = new byte[rawKeyData.Length]; if (newKeyEncryptor.ChecksumCalculatorFactory.AlgorithmDetails.Algorithm != HashAlgorithmTag.MD5) { throw new PgpException("MD5 Digest Calculator required for version 3 key encryptor."); } // // 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 = newKeyEncryptor.Wrap(Arrays.CopyOfRange(rawKeyData, pos + 2, pos + 2 + encLen)).Collect(); iv = newKeyEncryptor.AlgorithmDetails.GetIV(); } else { byte[] tmpIv = new byte[iv.Length]; Array.Copy(keyData, pos - iv.Length, tmpIv, 0, tmpIv.Length); newKeyEncryptor = newKeyEncryptor.WithIV(tmpIv); tmp = newKeyEncryptor.Wrap(Arrays.CopyOfRange(rawKeyData, pos + 2, pos + 2 + encLen)).Collect(); } 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]; s2k = newKeyEncryptor.AlgorithmDetails.S2k; newEncAlgorithm = newKeyEncryptor.AlgorithmDetails.Algorithm; } else { keyData = newKeyEncryptor.Wrap(rawKeyData).Collect(); iv = newKeyEncryptor.AlgorithmDetails.GetIV(); s2k = newKeyEncryptor.AlgorithmDetails.S2k; newEncAlgorithm = newKeyEncryptor.AlgorithmDetails.Algorithm; } } SecretKeyPacket secret; if (key.secret is SecretSubkeyPacket) { secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } else { secret = new SecretKeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } return(new PgpSecretKey(secret, key.pub)); }
internal static KeyParameter DoMakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag algorithm, S2k s2k, byte[] rawPassPhrase, bool clearPassPhrase) { int keySize = GetKeySize(algorithm); byte[] pBytes = rawPassPhrase; byte[] keyBytes = new byte[(keySize + 7) / 8]; int generatedBytes = 0; int loopCount = 0; while (generatedBytes < keyBytes.Length) { IDigest digest; if (s2k != null) { string digestName = GetDigestName(s2k.HashAlgorithm); try { digest = DigestUtilities.GetDigest(digestName); } catch (Exception e) { throw new PgpException("can't find S2k digest", e); } for (int i = 0; i != loopCount; i++) { digest.Update(0); } byte[] iv = s2k.GetIV(); switch (s2k.Type) { case S2k.Simple: digest.BlockUpdate(pBytes, 0, pBytes.Length); break; case S2k.Salted: digest.BlockUpdate(iv, 0, iv.Length); digest.BlockUpdate(pBytes, 0, pBytes.Length); break; case S2k.SaltedAndIterated: long count = s2k.IterationCount; digest.BlockUpdate(iv, 0, iv.Length); digest.BlockUpdate(pBytes, 0, pBytes.Length); count -= iv.Length + pBytes.Length; while (count > 0) { if (count < iv.Length) { digest.BlockUpdate(iv, 0, (int)count); break; } else { digest.BlockUpdate(iv, 0, iv.Length); count -= iv.Length; } if (count < pBytes.Length) { digest.BlockUpdate(pBytes, 0, (int)count); count = 0; } else { digest.BlockUpdate(pBytes, 0, pBytes.Length); count -= pBytes.Length; } } break; default: throw new PgpException("unknown S2k type: " + s2k.Type); } } else { try { digest = DigestUtilities.GetDigest("MD5"); for (int i = 0; i != loopCount; i++) { digest.Update(0); } digest.BlockUpdate(pBytes, 0, pBytes.Length); } catch (Exception e) { throw new PgpException("can't find MD5 digest", e); } } byte[] dig = DigestUtilities.DoFinal(digest); if (dig.Length > (keyBytes.Length - generatedBytes)) { Array.Copy(dig, 0, keyBytes, generatedBytes, keyBytes.Length - generatedBytes); } else { Array.Copy(dig, 0, keyBytes, generatedBytes, dig.Length); } generatedBytes += dig.Length; loopCount++; } if (clearPassPhrase && rawPassPhrase != null) { Array.Clear(rawPassPhrase, 0, rawPassPhrase.Length); } return(MakeKey(algorithm, keyBytes)); }
internal PgpSecretKey( PgpKeyPair keyPair, SymmetricKeyAlgorithmTag encAlgorithm, char[] passPhrase, bool useSHA1, SecureRandom rand) { PublicKeyPacket pubPk = keyPair.PublicKey.publicPk; BcpgObject secKey; switch (keyPair.PublicKey.Algorithm) { case PublicKeyAlgorithmTag.RsaEncrypt: case PublicKeyAlgorithmTag.RsaSign: case PublicKeyAlgorithmTag.RsaGeneral: RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) keyPair.PrivateKey.Key; secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q); break; case PublicKeyAlgorithmTag.Dsa: DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) keyPair.PrivateKey.Key; secKey = new DsaSecretBcpgKey(dsK.X); break; case PublicKeyAlgorithmTag.ElGamalEncrypt: case PublicKeyAlgorithmTag.ElGamalGeneral: ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) keyPair.PrivateKey.Key; secKey = new ElGamalSecretBcpgKey(esK.X); break; default: throw new PgpException("unknown key class"); } string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm); IBufferedCipher c = null; if (cName != null) { try { c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } } try { MemoryStream bOut = new MemoryStream(); BcpgOutputStream pOut = new BcpgOutputStream(bOut); pOut.WriteObject(secKey); byte[] keyData = bOut.ToArray(); byte[] checksumBytes = Checksum(useSHA1, keyData, keyData.Length); pOut.Write(checksumBytes); byte[] bOutData = bOut.ToArray(); if (c != null) { byte[] iv = new byte[8]; rand.NextBytes(iv); S2k s2k = new S2k(HashAlgorithmTag.Sha1, iv, 0x60); KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase); iv = new byte[c.GetBlockSize()]; rand.NextBytes(iv); c.Init(true, new ParametersWithIV(key, iv)); byte[] encData = c.DoFinal(bOutData); int usage = useSHA1 ? SecretKeyPacket.UsageSha1 : SecretKeyPacket.UsageChecksum; this.secret = new SecretKeyPacket(pubPk, encAlgorithm, usage, s2k, iv, encData); } else { this.secret = new SecretKeyPacket(pubPk, encAlgorithm, null, null, bOutData); } this.trust = null; } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } this.keySigs = new ArrayList(); }
/// <remarks> /// The passphrase is encoded to bytes using UTF8 (Encoding.UTF8.GetBytes). /// </remarks> public static KeyParameter MakeKeyFromPassPhraseUtf8(SymmetricKeyAlgorithmTag algorithm, S2k s2k, char[] passPhrase) { return DoMakeKeyFromPassPhrase(algorithm, s2k, EncodePassPhrase(passPhrase, true), true); }
/// <summary> /// Return a copy of the passed in secret key, encrypted using a new password /// and the passed in algorithm. /// </summary> /// <param name="key">The PgpSecretKey to be copied.</param> /// <param name="oldPassPhrase">The current password for the key.</param> /// <param name="newPassPhrase">The new password for the key.</param> /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param> /// <param name="rand">Source of randomness.</param> public static PgpSecretKey CopyWithNewPassword( PgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand) { byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase); int s2kUsage = key.secret.S2kUsage; byte[] iv = null; S2k s2k = null; byte[] keyData; if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null) { s2kUsage = SecretKeyPacket.UsageNone; if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1) // SHA-1 hash, need to rewrite Checksum { keyData = new byte[rawKeyData.Length - 18]; Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2); byte[] check = Checksum(false, keyData, keyData.Length - 2); keyData[keyData.Length - 2] = check[0]; keyData[keyData.Length - 1] = check[1]; } else { keyData = rawKeyData; } } else { IBufferedCipher c; try { string cName = PgpUtilities.GetSymmetricCipherName(newEncAlgorithm); c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding"); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } iv = new byte[8]; rand.NextBytes(iv); s2k = new S2k(HashAlgorithmTag.Sha1, iv, 0x60); try { KeyParameter sKey = PgpUtilities.MakeKeyFromPassPhrase(newEncAlgorithm, s2k, newPassPhrase); iv = new byte[c.GetBlockSize()]; rand.NextBytes(iv); c.Init(true, new ParametersWithIV(sKey, iv)); keyData = c.DoFinal(rawKeyData); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception encrypting key", e); } } SecretKeyPacket secret; if (key.secret is SecretSubkeyPacket) { secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } else { secret = new SecretKeyPacket(key.secret.PublicKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData); } if (key.subSigs == null) { return new PgpSecretKey(secret, key.trust, key.keySigs, key.ids, key.idTrusts, key.idSigs, key.pub); } return new PgpSecretKey(secret, key.trust, key.subSigs, key.pub); }
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); }
internal PbeMethod(SymmetricKeyAlgorithmTag encAlgorithm, S2k s2K, KeyParameter key) { this.EncAlgorithm = encAlgorithm; this._s2K = s2K; this.Key = key; }
/// <summary>Add a PBE encryption method to the encrypted object.</summary> public void AddMethod( char[] passPhrase, HashAlgorithmTag s2kDigest) { byte[] iv = new byte[8]; rand.NextBytes(iv); S2k s2k = new S2k(s2kDigest, iv, 0x60); methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.MakeKeyFromPassPhrase(defAlgorithm, s2k, passPhrase))); }
/// <summary>Add a PBE encryption method to the encrypted object.</summary> public void AddMethod(char[] passPhrase, HashAlgorithmTag s2KDigest) { var iv = new byte[8]; _rand.NextBytes(iv); var s2K = new S2k(s2KDigest, iv, 0x60); _methods.Add(new PbeMethod(_defAlgorithm, s2K, PgpUtilities.MakeKeyFromPassPhrase(_defAlgorithm, s2K, passPhrase))); }
public static KeyParameter MakeKeyFromPassPhrase( SymmetricKeyAlgorithmTag algorithm, S2k s2k, char[] passPhrase) { // Changed pBytes to get string via encoding // this should use the OS encoding. // // vvv EDDINGTON var encoding = System.Text.Encoding.UTF8; int keySize = GetKeySize(algorithm); byte[] pBytes = encoding.GetBytes(new string(passPhrase)); byte[] keyBytes = new byte[(keySize + 7) / 8]; // ^^^ EDDINGTON int generatedBytes = 0; int loopCount = 0; while (generatedBytes < keyBytes.Length) { IDigest digest; if (s2k != null) { string digestName = GetDigestName(s2k.HashAlgorithm); try { digest = DigestUtilities.GetDigest(digestName); } catch (Exception e) { throw new PgpException("can't find S2k digest", e); } for (int i = 0; i != loopCount; i++) { digest.Update(0); } byte[] iv = s2k.GetIV(); switch (s2k.Type) { case S2k.Simple: digest.BlockUpdate(pBytes, 0, pBytes.Length); break; case S2k.Salted: digest.BlockUpdate(iv, 0, iv.Length); digest.BlockUpdate(pBytes, 0, pBytes.Length); break; case S2k.SaltedAndIterated: long count = s2k.IterationCount; digest.BlockUpdate(iv, 0, iv.Length); digest.BlockUpdate(pBytes, 0, pBytes.Length); count -= iv.Length + pBytes.Length; while (count > 0) { if (count < iv.Length) { digest.BlockUpdate(iv, 0, (int)count); break; } else { digest.BlockUpdate(iv, 0, iv.Length); count -= iv.Length; } if (count < pBytes.Length) { digest.BlockUpdate(pBytes, 0, (int)count); count = 0; } else { digest.BlockUpdate(pBytes, 0, pBytes.Length); count -= pBytes.Length; } } break; default: throw new PgpException("unknown S2k type: " + s2k.Type); } } else { try { digest = DigestUtilities.GetDigest("MD5"); for (int i = 0; i != loopCount; i++) { digest.Update(0); } digest.BlockUpdate(pBytes, 0, pBytes.Length); } catch (Exception e) { throw new PgpException("can't find MD5 digest", e); } } byte[] dig = DigestUtilities.DoFinal(digest); if (dig.Length > (keyBytes.Length - generatedBytes)) { Array.Copy(dig, 0, keyBytes, generatedBytes, keyBytes.Length - generatedBytes); } else { Array.Copy(dig, 0, keyBytes, generatedBytes, dig.Length); } generatedBytes += dig.Length; loopCount++; } Array.Clear(pBytes, 0, pBytes.Length); return MakeKey(algorithm, keyBytes); }
public PgpPbeKeyEncryptionParameters(SymmetricKeyAlgorithmTag encAlgorithm, S2k s2k, byte[] iv) { this.Algorithm = encAlgorithm; this.S2k = s2k; this.mIv = Arrays.Clone(iv); }
public static KeyParameter MakeKeyFromPassPhrase( SymmetricKeyAlgorithmTag algorithm, S2k s2k, char[] passPhrase) { int keySize = GetKeySize(algorithm); byte[] pBytes = Strings.ToByteArray(new string(passPhrase)); byte[] keyBytes = new byte[(keySize + 7) / 8]; int generatedBytes = 0; int loopCount = 0; while (generatedBytes < keyBytes.Length) { IDigest digest; if (s2k != null) { try { switch (s2k.HashAlgorithm) { case HashAlgorithmTag.Sha1: digest = DigestUtilities.GetDigest("SHA1"); break; default: throw new PgpException("unknown hash algorithm: " + s2k.HashAlgorithm); } } catch (Exception e) { throw new PgpException("can't find S2k digest", e); } for (int i = 0; i != loopCount; i++) { digest.Update(0); } byte[] iv = s2k.GetIV(); switch (s2k.Type) { case S2k.Simple: digest.BlockUpdate(pBytes, 0, pBytes.Length); break; case S2k.Salted: digest.BlockUpdate(iv, 0, iv.Length); digest.BlockUpdate(pBytes, 0, pBytes.Length); break; case S2k.SaltedAndIterated: long count = s2k.IterationCount; digest.BlockUpdate(iv, 0, iv.Length); digest.BlockUpdate(pBytes, 0, pBytes.Length); count -= iv.Length + pBytes.Length; while (count > 0) { if (count < iv.Length) { digest.BlockUpdate(iv, 0, (int)count); break; } else { digest.BlockUpdate(iv, 0, iv.Length); count -= iv.Length; } if (count < pBytes.Length) { digest.BlockUpdate(pBytes, 0, (int)count); count = 0; } else { digest.BlockUpdate(pBytes, 0, pBytes.Length); count -= pBytes.Length; } } break; default: throw new PgpException("unknown S2k type: " + s2k.Type); } } else { try { digest = DigestUtilities.GetDigest("MD5"); for (int i = 0; i != loopCount; i++) { digest.Update(0); } digest.BlockUpdate(pBytes, 0, pBytes.Length); } catch (Exception e) { throw new PgpException("can't find MD5 digest", e); } } byte[] dig = DigestUtilities.DoFinal(digest); if (dig.Length > (keyBytes.Length - generatedBytes)) { Array.Copy(dig, 0, keyBytes, generatedBytes, keyBytes.Length - generatedBytes); } else { Array.Copy(dig, 0, keyBytes, generatedBytes, dig.Length); } generatedBytes += dig.Length; loopCount++; } Array.Clear(pBytes, 0, pBytes.Length); return MakeKey(algorithm, keyBytes); }
internal void DoAddMethod(byte[] rawPassPhrase, bool clearPassPhrase, HashAlgorithmTag s2kDigest) { byte[] iv = new byte[8]; rand.NextBytes(iv); S2k s2k = new S2k(s2kDigest, iv, 0x60); methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.DoMakeKeyFromPassPhrase(defAlgorithm, s2k, rawPassPhrase, clearPassPhrase))); }