/// <summary>Add a PBE encryption method to the encrypted object.</summary> public void AddMethod(ReadOnlySpan <byte> rawPassPhrase, PgpHashAlgorithm s2kDigest) { S2k s2k = PgpUtilities.GenerateS2k(s2kDigest, 0x60); byte[] key = new byte[PgpUtilities.GetKeySize(defAlgorithm) / 8]; S2kBasedEncryption.MakeKey(rawPassPhrase, s2kDigest, s2k.GetIV(), s2k.IterationCount, key); methods.Add(new PbeMethod(defAlgorithm, s2k, key)); }
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); }
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) { 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 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); }
internal static byte[] MakeKeyFromPassPhrase( IDigestFactory <PgpDigestTypeIdentifier> digestFactory, SymmetricKeyAlgorithmTag algorithm, S2k s2k, char[] passPhrase) { int keySize = 0; switch (algorithm) { case SymmetricKeyAlgorithmTag.TripleDes: keySize = 192; break; case SymmetricKeyAlgorithmTag.Idea: keySize = 128; break; case SymmetricKeyAlgorithmTag.Cast5: keySize = 128; break; case SymmetricKeyAlgorithmTag.Blowfish: keySize = 128; break; case SymmetricKeyAlgorithmTag.Safer: keySize = 128; break; case SymmetricKeyAlgorithmTag.Des: keySize = 64; break; case SymmetricKeyAlgorithmTag.Aes128: keySize = 128; break; case SymmetricKeyAlgorithmTag.Aes192: keySize = 192; break; case SymmetricKeyAlgorithmTag.Aes256: keySize = 256; break; case SymmetricKeyAlgorithmTag.Twofish: keySize = 256; break; case SymmetricKeyAlgorithmTag.Camellia128: keySize = 128; break; case SymmetricKeyAlgorithmTag.Camellia192: keySize = 192; break; case SymmetricKeyAlgorithmTag.Camellia256: keySize = 256; break; default: throw new PgpException("unknown symmetric algorithm: " + algorithm); } byte[] pBytes = Strings.ToUtf8ByteArray(passPhrase); byte[] keyBytes = new byte[(keySize + 7) / 8]; int generatedBytes = 0; int loopCount = 0; if (s2k != null) { if (s2k.HashAlgorithm != digestFactory.AlgorithmDetails.Algorithm) { throw new PgpException("s2k/digestFactory mismatch"); } } else { if (digestFactory.AlgorithmDetails.Algorithm != HashAlgorithmTag.MD5) { throw new PgpException("digestFactory not for MD5"); } } IStreamCalculator <IBlockResult> digestCalculator = digestFactory.CreateCalculator(); Stream dOut = digestCalculator.Stream; try { while (generatedBytes < keyBytes.Length) { if (s2k != null) { for (int i = 0; i != loopCount; i++) { dOut.WriteByte(0); } byte[] iv = s2k.GetIV(); switch (s2k.Type) { case S2k.Simple: dOut.Write(pBytes, 0, pBytes.Length); break; case S2k.Salted: dOut.Write(iv, 0, iv.Length); dOut.Write(pBytes, 0, pBytes.Length); break; case S2k.SaltedAndIterated: long count = s2k.IterationCount; dOut.Write(iv, 0, iv.Length); dOut.Write(pBytes, 0, pBytes.Length); count -= iv.Length + pBytes.Length; while (count > 0) { if (count < iv.Length) { dOut.Write(iv, 0, (int)count); break; } else { dOut.Write(iv, 0, iv.Length); count -= iv.Length; } if (count < pBytes.Length) { dOut.Write(pBytes, 0, (int)count); count = 0; } else { dOut.Write(pBytes, 0, pBytes.Length); count -= pBytes.Length; } } break; default: throw new PgpException("unknown S2K type: " + s2k.Type); } } else { for (int i = 0; i != loopCount; i++) { dOut.WriteByte((byte)0); } dOut.Write(pBytes, 0, pBytes.Length); } dOut.Close(); byte[] dig = digestCalculator.GetResult().Collect(); 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++; } } catch (IOException e) { throw new PgpException("exception calculating digest: " + e.Message, e); } for (int i = 0; i != pBytes.Length; i++) { pBytes[i] = 0; } return(keyBytes); }
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)); }