public static ECDiffieHellmanKey CreatePrivate( ReadOnlySpan <byte> fingerprint, ReadOnlySpan <byte> password, ReadOnlySpan <byte> source, out int publicKeySize) { var ecParameters = ReadOpenPgpECParameters(source, out publicKeySize); // TODO: Validation byte kdfSize = source[publicKeySize]; var kdfParameters = source.Slice(publicKeySize + 1, kdfSize).ToArray(); byte[] paramsArray = new byte[source.Length - publicKeySize]; try { S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeySize + kdfSize + 1), paramsArray, out int bytesWritten); Debug.Assert(bytesWritten != 0); ecParameters.D = MPInteger.ReadInteger(paramsArray, out int dConsumed).ToArray(); return(new ECDiffieHellmanKey(CreateECDiffieHellman(ecParameters), kdfParameters, fingerprint.ToArray())); } finally { CryptographicOperations.ZeroMemory(paramsArray); CryptographicOperations.ZeroMemory(ecParameters.D); } }
public static DsaKey CreatePrivate( ReadOnlySpan <byte> password, ReadOnlySpan <byte> source, out int publicKeySize) { var dsaParameters = ReadOpenPgpPublicKey(source, out publicKeySize); byte[] xArray = new byte[source.Length - publicKeySize]; try { S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeySize), xArray, out int bytesWritten); dsaParameters.X = MPInteger.ReadInteger(xArray, out int xConsumed).ToArray(); // Make sure Q, X have the same length (DSA implementation on Windows requires it) int qxLength = Math.Max(dsaParameters.X.Length, dsaParameters.Q !.Length); ResizeArrayIfNeeded(ref dsaParameters.Q, qxLength); ResizeArrayIfNeeded(ref dsaParameters.X, qxLength); return(new DsaKey(DSA.Create(dsaParameters))); } finally { CryptographicOperations.ZeroMemory(xArray); CryptographicOperations.ZeroMemory(dsaParameters.X); } }
public bool TryDecryptSessionInfo(ReadOnlySpan <byte> encryptedSessionData, Span <byte> sessionData, out int bytesWritten) { var pEnc = MPInteger.ReadInteger(encryptedSessionData, out int pointBytesRead); encryptedSessionData = encryptedSessionData.Slice(pointBytesRead); int keyLen = encryptedSessionData[0]; var keyEnc = encryptedSessionData.Slice(1, keyLen); var publicParams = ecdh.PublicKey.ExportParameters(); var publicPoint = DecodePoint(pEnc); var otherEcdh = CreateECDiffieHellman(new ECParameters { Curve = publicParams.Curve, Q = publicPoint }); var derivedKey = ecdh.DeriveKeyFromHash( otherEcdh.PublicKey, PgpUtilities.GetHashAlgorithmName(this.hashAlgorithm), new byte[] { 0, 0, 0, 1 }, CreateUserKeyingMaterial(publicParams.Curve.Oid)); derivedKey = derivedKey.AsSpan(0, PgpUtilities.GetKeySize(this.symmetricAlgorithm) / 8).ToArray(); var C = SymmetricKeyWrap.AESKeyWrapDecrypt(derivedKey, keyEnc.ToArray()); var data = UnpadSessionData(C); if (sessionData.Length >= data.Length) { data.CopyTo(sessionData); bytesWritten = data.Length; return(true); } bytesWritten = 0; return(false); }
public byte[] EncryptSessionInfo(ReadOnlySpan <byte> sessionInfo) { var publicKeyParams = ecdh.PublicKey.ExportParameters(); // Generate the ephemeral key pair var ephemeralEcDh = CreateECDiffieHellman(publicKeyParams.Curve); var derivedKey = ephemeralEcDh.DeriveKeyFromHash( ecdh.PublicKey, PgpUtilities.GetHashAlgorithmName(this.hashAlgorithm), new byte[] { 0, 0, 0, 1 }, CreateUserKeyingMaterial(publicKeyParams.Curve.Oid)); derivedKey = derivedKey.AsSpan(0, PgpUtilities.GetKeySize(symmetricAlgorithm) / 8).ToArray(); byte[] paddedSessionData = PadSessionData(sessionInfo); byte[] C = SymmetricKeyWrap.AESKeyWrapEncrypt(derivedKey, paddedSessionData); var ep = ephemeralEcDh.PublicKey.ExportParameters(); byte[] VB = EncodePoint(ep.Q, publicKeyParams.Curve.Oid); byte[] rv = new byte[VB.Length + 2 + 1 + C.Length]; MPInteger.TryWriteInteger(VB, rv, out _); //Array.Copy(VB, 0, rv, 0, VB.Length); rv[VB.Length + 2] = (byte)C.Length; Array.Copy(C, 0, rv, VB.Length + 3, C.Length); return(rv); }
private static void WriteOpenPgpPublicKey(DSAParameters dsaParameters, Span <byte> destination) { MPInteger.TryWriteInteger(dsaParameters.P, destination, out int pWritten); MPInteger.TryWriteInteger(dsaParameters.Q, destination.Slice(pWritten), out int qWritten); MPInteger.TryWriteInteger(dsaParameters.G, destination.Slice(pWritten + qWritten), out int gWritten); MPInteger.TryWriteInteger(dsaParameters.Y, destination.Slice(pWritten + qWritten + gWritten), out int yWritten); }
public byte[] ExportPrivateKey( ReadOnlySpan <byte> passwordBytes, S2kParameters s2kParameters) { DSAParameters dsaParameters = new DSAParameters(); byte[] secretPart = Array.Empty <byte>(); try { dsaParameters = dsa.ExportParameters(true); secretPart = CryptoPool.Rent(MPInteger.GetMPEncodedLength(dsaParameters.X !)); MPInteger.TryWriteInteger(dsaParameters.X, secretPart, out var secretSize); int publicKeySize = MPInteger.GetMPEncodedLength(dsaParameters.P !, dsaParameters.Q !, dsaParameters.G !, dsaParameters.Y !); int encryptedSecretSize = S2kBasedEncryption.GetEncryptedLength(s2kParameters, secretSize); int expectedLength = publicKeySize + encryptedSecretSize; var destination = new byte[expectedLength]; WriteOpenPgpPublicKey(dsaParameters, destination); S2kBasedEncryption.EncryptSecretKey(passwordBytes, s2kParameters, secretPart.AsSpan(0, secretSize), destination.AsSpan(publicKeySize)); return(destination); } finally { CryptoPool.Return(secretPart); CryptographicOperations.ZeroMemory(dsaParameters.X); } }
public byte[] EncryptSessionInfo(ReadOnlySpan <byte> sessionInfo) { var encryptedSessionInfo = rsa.Encrypt(sessionInfo.ToArray(), RSAEncryptionPadding.Pkcs1); var mp = new byte[MPInteger.GetMPEncodedLength(encryptedSessionInfo)]; MPInteger.TryWriteInteger(encryptedSessionInfo, mp, out var _); return(mp); }
public byte[] CreateSignature(ReadOnlySpan <byte> rgbHash, PgpHashAlgorithm hashAlgorithm) { byte[] ieeeSignature = ecdsa.SignHash(rgbHash.ToArray(), DSASignatureFormat.IeeeP1363FixedFieldConcatenation); byte[] pgpSignature = new byte[ieeeSignature.Length + 4]; // Maximum possible length MPInteger.TryWriteInteger(ieeeSignature.AsSpan(0, ieeeSignature.Length / 2), pgpSignature, out int rWritten); MPInteger.TryWriteInteger(ieeeSignature.AsSpan(ieeeSignature.Length / 2), pgpSignature.AsSpan(rWritten), out int sWritten); return(pgpSignature.AsSpan(0, rWritten + sWritten).ToArray()); }
public bool VerifySignature( ReadOnlySpan <byte> rgbHash, ReadOnlySpan <byte> rgbSignature, PgpHashAlgorithm hashAlgorithm) { var signature = MPInteger.ReadInteger(rgbSignature, out var _); return(rsa.VerifyHash(rgbHash, signature, PgpUtilities.GetHashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pkcs1)); }
public static RSAParameters ReadOpenPgpPublicKey(ReadOnlySpan <byte> source, out int bytesRead) { var rsaParameters = new RSAParameters(); rsaParameters.Modulus = MPInteger.ReadInteger(source, out int modulusConsumed).ToArray(); source = source.Slice(modulusConsumed); rsaParameters.Exponent = MPInteger.ReadInteger(source, out int exponentConsumed).ToArray(); bytesRead = modulusConsumed + exponentConsumed; return(rsaParameters); }
public byte[] CreateSignature( ReadOnlySpan <byte> rgbHash, PgpHashAlgorithm hashAlgorithm) { var signature = rsa.SignHash(rgbHash.ToArray(), PgpUtilities.GetHashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pkcs1); var signatureBytes = new byte[MPInteger.GetMPEncodedLength(signature)]; MPInteger.TryWriteInteger(signature, signatureBytes, out var _); return(signatureBytes); }
public byte[] ExportPublicKey() { var rsaParameters = rsa.ExportParameters(false); int expectedLength = MPInteger.GetMPEncodedLength(rsaParameters.Modulus !, rsaParameters.Exponent !); var destination = new byte[expectedLength]; MPInteger.TryWriteInteger(rsaParameters.Modulus, destination, out int modulusWritten); MPInteger.TryWriteInteger(rsaParameters.Exponent, destination.AsSpan(modulusWritten), out int exponentWritten); return(destination.AsSpan(0, modulusWritten + exponentWritten).ToArray()); }
public byte[] EncryptSessionInfo(ReadOnlySpan <byte> sessionInfo) { var encryptedData = elGamal.Encrypt(sessionInfo, RSAEncryptionPadding.Pkcs1); var g = encryptedData.Slice(0, encryptedData.Length / 2); var p = encryptedData.Slice(encryptedData.Length / 2); var mp = new byte[MPInteger.GetMPEncodedLength(g) + MPInteger.GetMPEncodedLength(p)]; MPInteger.TryWriteInteger(g, mp, out var gWritten); MPInteger.TryWriteInteger(p, mp.AsSpan(gWritten), out var _); return(mp); }
public byte[] CreateSignature(ReadOnlySpan <byte> rgbHash, PgpHashAlgorithm hashAlgorithm) { byte[] ieeeSignature = dsa.CreateSignature(rgbHash.ToArray(), DSASignatureFormat.IeeeP1363FixedFieldConcatenation); var r = ieeeSignature.AsSpan(0, ieeeSignature.Length / 2); var s = ieeeSignature.AsSpan(ieeeSignature.Length / 2); byte[] pgpSignature = new byte[MPInteger.GetMPEncodedLength(r) + MPInteger.GetMPEncodedLength(s)]; MPInteger.TryWriteInteger(r, pgpSignature, out int rWritten); MPInteger.TryWriteInteger(s, pgpSignature.AsSpan(rWritten), out int _); return(pgpSignature); }
private static ElGamalParameters ReadOpenPgpPublicKey(ReadOnlySpan <byte> source, out int bytesRead) { var elgamalParameters = new ElGamalParameters(); elgamalParameters.P = MPInteger.ReadInteger(source, out int pConsumed).ToArray(); source = source.Slice(pConsumed); elgamalParameters.G = MPInteger.ReadInteger(source, out int gConsumed).ToArray(); source = source.Slice(gConsumed); elgamalParameters.Y = MPInteger.ReadInteger(source, out int yConsumed).ToArray(); bytesRead = pConsumed + gConsumed + yConsumed; return(elgamalParameters); }
protected void WriteOpenPgpECParameters(ECParameters ecParameters, Span <byte> destination, out int bytesWritten) { var writer = new AsnWriter(AsnEncodingRules.DER); writer.WriteObjectIdentifier(ecParameters.Curve.Oid.Value !); var encodedPoint = EncodePoint(ecParameters.Q, ecParameters.Curve.Oid); var encodedOid = writer.Encode(); encodedOid.AsSpan(1).CopyTo(destination); MPInteger.TryWriteInteger(encodedPoint, destination.Slice(encodedOid.Length - 1), out bytesWritten); bytesWritten += encodedOid.Length - 1; }
public bool TryDecryptSessionInfo(ReadOnlySpan <byte> encryptedSessionData, Span <byte> sessionData, out int bytesWritten) { var mp = MPInteger.ReadInteger(encryptedSessionData, out var _); var data = rsa.Decrypt(mp.ToArray(), RSAEncryptionPadding.Pkcs1); if (sessionData.Length >= data.Length) { data.CopyTo(sessionData); bytesWritten = data.Length; return(true); } bytesWritten = 0; return(false); }
public bool VerifySignature( ReadOnlySpan <byte> rgbHash, ReadOnlySpan <byte> rgbSignature, PgpHashAlgorithm hashAlgorithm) { var asnWriter = new AsnWriter(AsnEncodingRules.DER); using (var scope = asnWriter.PushSequence()) { asnWriter.WriteIntegerUnsigned(MPInteger.ReadInteger(rgbSignature, out int rConsumed)); asnWriter.WriteIntegerUnsigned(MPInteger.ReadInteger(rgbSignature.Slice(rConsumed), out var _)); } return(dsa.VerifySignature(rgbHash, asnWriter.Encode(), DSASignatureFormat.Rfc3279DerSequence)); }
public byte[] ExportPrivateKey( ReadOnlySpan <byte> passwordBytes, S2kParameters s2kParameters) { RSAParameters rsaParameters = new RSAParameters(); byte[] secretPart = Array.Empty <byte>(); try { rsaParameters = rsa.ExportParameters(true); secretPart = CryptoPool.Rent(MPInteger.GetMPEncodedLength(rsaParameters.D !, rsaParameters.P !, rsaParameters.Q !, rsaParameters.InverseQ !)); MPInteger.TryWriteInteger(rsaParameters.D, secretPart, out var dBytesWritten); MPInteger.TryWriteInteger(rsaParameters.P, secretPart.AsSpan(dBytesWritten), out var pBytesWritten); MPInteger.TryWriteInteger(rsaParameters.Q, secretPart.AsSpan(dBytesWritten + pBytesWritten), out var qBytesWritten); MPInteger.TryWriteInteger(rsaParameters.InverseQ, secretPart.AsSpan(dBytesWritten + pBytesWritten + qBytesWritten), out var iqBytesWritten); int secretSize = dBytesWritten + pBytesWritten + qBytesWritten + iqBytesWritten; int encryptedSecretSize = S2kBasedEncryption.GetEncryptedLength(s2kParameters, secretSize); int expectedLength = MPInteger.GetMPEncodedLength(rsaParameters.Modulus !, rsaParameters.Exponent !) + encryptedSecretSize; var destination = new byte[expectedLength]; MPInteger.TryWriteInteger(rsaParameters.Modulus, destination, out int modulusWritten); MPInteger.TryWriteInteger(rsaParameters.Exponent, destination.AsSpan(modulusWritten), out int exponentWritten); S2kBasedEncryption.EncryptSecretKey(passwordBytes, s2kParameters, secretPart.AsSpan(0, secretSize), destination.AsSpan(modulusWritten + exponentWritten)); return(destination.AsSpan(0, modulusWritten + exponentWritten + encryptedSecretSize).ToArray()); } finally { CryptoPool.Return(secretPart); CryptographicOperations.ZeroMemory(rsaParameters.D); CryptographicOperations.ZeroMemory(rsaParameters.P); CryptographicOperations.ZeroMemory(rsaParameters.Q); CryptographicOperations.ZeroMemory(rsaParameters.InverseQ); CryptographicOperations.ZeroMemory(rsaParameters.DP); CryptographicOperations.ZeroMemory(rsaParameters.DQ); } }
public byte[] ExportPrivateKey( ReadOnlySpan <byte> passwordBytes, S2kParameters s2kParameters) { ECParameters ecParameters = new ECParameters(); byte[] secretPart = Array.Empty <byte>(); try { ecParameters = ecdh.ExportParameters(true); if (ecdh is X25519) { Array.Reverse(ecParameters.D !); } int secretSize = MPInteger.GetMPEncodedLength(ecParameters.D !); secretPart = CryptoPool.Rent(secretSize); MPInteger.TryWriteInteger(ecParameters.D, secretPart, out var _); int encryptedSecretLength = S2kBasedEncryption.GetEncryptedLength(s2kParameters, secretSize); int estimatedLength = 32 /* OID */ + MPInteger.GetMPEncodedLength(ecParameters.Q.X !, ecParameters.Q.Y !) + 1 /* EC Point type */ + 4 /* KDF Parameters */ + encryptedSecretLength; var destination = new byte[estimatedLength]; WriteOpenPgpECParameters(ecParameters, destination, out int bytesWritten); WriteKDFParameters(destination.AsSpan(bytesWritten)); S2kBasedEncryption.EncryptSecretKey(passwordBytes, s2kParameters, secretPart.AsSpan(0, secretSize), destination.AsSpan(bytesWritten + 4)); return(destination.AsSpan(0, bytesWritten + 4 + encryptedSecretLength).ToArray()); } finally { CryptoPool.Return(secretPart); if (ecParameters.D != null) { CryptographicOperations.ZeroMemory(ecParameters.D); } } }
public bool TryDecryptSessionInfo(ReadOnlySpan <byte> encryptedSessionData, Span <byte> sessionData, out int bytesWritten) { var g = MPInteger.ReadInteger(encryptedSessionData, out var gBytesRead); var p = MPInteger.ReadInteger(encryptedSessionData.Slice(gBytesRead), out var _); var halfLength = Math.Max(g.Length, p.Length); var inputData = new byte[halfLength * 2]; g.CopyTo(inputData.AsSpan(halfLength - g.Length)); p.CopyTo(inputData.AsSpan(inputData.Length - p.Length)); var data = elGamal.Decrypt(inputData, RSAEncryptionPadding.Pkcs1); if (sessionData.Length >= data.Length) { data.CopyTo(sessionData); bytesWritten = data.Length; return(true); } bytesWritten = 0; return(false); }
private static DSAParameters ReadOpenPgpPublicKey(ReadOnlySpan <byte> source, out int bytesRead) { var dsaParameters = new DSAParameters(); dsaParameters.P = MPInteger.ReadInteger(source, out int pConsumed).ToArray(); source = source.Slice(pConsumed); dsaParameters.Q = MPInteger.ReadInteger(source, out int qConsumed).ToArray(); source = source.Slice(qConsumed); dsaParameters.G = MPInteger.ReadInteger(source, out int gConsumed).ToArray(); source = source.Slice(gConsumed); dsaParameters.Y = MPInteger.ReadInteger(source, out int yConsumed).ToArray(); bytesRead = pConsumed + qConsumed + gConsumed + yConsumed; // Make sure P, G, Y have the same length (DSA implementation on Windows requires it) int pgyLength = Math.Max(Math.Max(dsaParameters.P !.Length, dsaParameters.G !.Length), dsaParameters.Y !.Length); ResizeArrayIfNeeded(ref dsaParameters.P, pgyLength); ResizeArrayIfNeeded(ref dsaParameters.G, pgyLength); ResizeArrayIfNeeded(ref dsaParameters.Y, pgyLength); return(dsaParameters); }
public new static EdDsaKey CreatePrivate( ReadOnlySpan <byte> password, ReadOnlySpan <byte> source, out int publicKeySize) { var ecParameters = ReadOpenPgpECParameters(source, out publicKeySize); byte[] paramsArray = new byte[source.Length - publicKeySize]; try { S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeySize), paramsArray, out int bytesWritten); Debug.Assert(bytesWritten != 0); ecParameters.D = MPInteger.ReadInteger(paramsArray, out int dConsumed).ToArray(); return(new EdDsaKey(CreateEdDsa(ecParameters))); } finally { CryptographicOperations.ZeroMemory(paramsArray); CryptographicOperations.ZeroMemory(ecParameters.D); } }
public static ElGamalKey CreatePrivate( ReadOnlySpan <byte> password, ReadOnlySpan <byte> source, out int bytesRead) { var elgamalParameters = ReadOpenPgpPublicKey(source, out bytesRead); byte[] xArray = new byte[source.Length - bytesRead]; try { S2kBasedEncryption.DecryptSecretKey(password, source.Slice(bytesRead), xArray, out int bytesWritten); elgamalParameters.X = MPInteger.ReadInteger(xArray, out int xConsumed).ToArray(); bytesRead = source.Length; return(new ElGamalKey(ElGamal.Create(elgamalParameters))); } finally { CryptographicOperations.ZeroMemory(xArray); CryptographicOperations.ZeroMemory(elgamalParameters.X); } }
protected static ECParameters ReadOpenPgpECParameters(ReadOnlySpan <byte> source, out int bytesRead) { ECParameters ecParameters = new ECParameters(); int oidLength = source[0]; // TODO: Validate oidLength var oidBytes = new byte[oidLength + 2]; oidBytes[0] = 6; oidBytes[1] = (byte)oidLength; source.Slice(1, oidLength).CopyTo(oidBytes.AsSpan(2)); var oid = new Oid(AsnDecoder.ReadObjectIdentifier(oidBytes, AsnEncodingRules.DER, out _)); ecParameters.Curve = ECCurve.CreateFromOid(oid); var pointBytes = MPInteger.ReadInteger(source.Slice(oidLength + 1), out bytesRead); bytesRead += oidLength + 1; ecParameters.Q = DecodePoint(pointBytes); return(ecParameters); }
public static RsaKey CreatePrivate( ReadOnlySpan <byte> password, ReadOnlySpan <byte> source, out int publicKeyBytes, int version = 4) { var rsaParameters = ReadOpenPgpPublicKey(source, out publicKeyBytes); byte[] paramsArray = new byte[source.Length - publicKeyBytes]; try { S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeyBytes), paramsArray, out int bytesWritten, version); Debug.Assert(bytesWritten != 0); int halfModulusLength = (rsaParameters.Modulus !.Length + 1) / 2; rsaParameters.D = new byte[rsaParameters.Modulus.Length]; rsaParameters.P = new byte[halfModulusLength]; rsaParameters.Q = new byte[halfModulusLength]; rsaParameters.DP = new byte[halfModulusLength]; rsaParameters.DQ = new byte[halfModulusLength]; rsaParameters.InverseQ = new byte[halfModulusLength]; var privateSource = new ReadOnlySpan <byte>(paramsArray); var d = MPInteger.ReadInteger(privateSource, out int dConsumed); privateSource = privateSource.Slice(dConsumed); var p = MPInteger.ReadInteger(privateSource, out int pConsumed); privateSource = privateSource.Slice(pConsumed); var q = MPInteger.ReadInteger(privateSource, out int qConsumed); //source = source.Slice(qConsumed); // Technically InverseQ follows but it's often incorrect // FIXME: These BigIntegers cannot be cleared from memory var D = new BigInteger(d, isBigEndian: true, isUnsigned: true); var P = new BigInteger(p, isBigEndian: true, isUnsigned: true); var Q = new BigInteger(q, isBigEndian: true, isUnsigned: true); var DP = BigInteger.Remainder(D, P - BigInteger.One); var DQ = BigInteger.Remainder(D, Q - BigInteger.One); // Lot of the public keys in the test suite have this wrong (switched P/Q) var InverseQ = BigInteger.ModPow(Q, P - BigInteger.One - BigInteger.One, P); d.CopyTo(rsaParameters.D.AsSpan(rsaParameters.D.Length - d.Length)); p.CopyTo(rsaParameters.P.AsSpan(rsaParameters.P.Length - p.Length)); q.CopyTo(rsaParameters.Q.AsSpan(rsaParameters.Q.Length - q.Length)); DP.TryWriteBytes(rsaParameters.DP.AsSpan(rsaParameters.DP.Length - DP.GetByteCount(isUnsigned: true)), out var _, isBigEndian: true, isUnsigned: true); DQ.TryWriteBytes(rsaParameters.DQ.AsSpan(rsaParameters.DQ.Length - DQ.GetByteCount(isUnsigned: true)), out var _, isBigEndian: true, isUnsigned: true); InverseQ.TryWriteBytes(rsaParameters.InverseQ.AsSpan(rsaParameters.InverseQ.Length - InverseQ.GetByteCount(isUnsigned: true)), out var _, isBigEndian: true, isUnsigned: true); return(new RsaKey(RSA.Create(rsaParameters))); } finally { CryptographicOperations.ZeroMemory(paramsArray); CryptographicOperations.ZeroMemory(rsaParameters.D); CryptographicOperations.ZeroMemory(rsaParameters.P); CryptographicOperations.ZeroMemory(rsaParameters.Q); CryptographicOperations.ZeroMemory(rsaParameters.DP); CryptographicOperations.ZeroMemory(rsaParameters.DQ); CryptographicOperations.ZeroMemory(rsaParameters.InverseQ); } }
private static void WriteOpenPgpPublicKey(ElGamalParameters elgamalParameters, Span <byte> destination) { MPInteger.TryWriteInteger(elgamalParameters.P, destination, out int pWritten); MPInteger.TryWriteInteger(elgamalParameters.G, destination.Slice(pWritten), out int gWritten); MPInteger.TryWriteInteger(elgamalParameters.Y, destination.Slice(pWritten + gWritten), out int yWritten); }
public static void EncryptSecretKey( ReadOnlySpan <byte> password, S2kParameters s2kParameters, ReadOnlySpan <byte> source, Span <byte> destination, int version = 4) { if (password.Length == 0) { destination[0] = (byte)S2kUsageTag.None; source.CopyTo(destination.Slice(1)); return; } using var c = PgpUtilities.GetSymmetricAlgorithm(s2kParameters.EncryptionAlgorithm); int keySizeInBytes = (c.KeySize + 7) / 8; Span <byte> keyBytes = stackalloc byte[keySizeInBytes]; if (version <= 3) { MakeKey(password, PgpHashAlgorithm.MD5, Array.Empty <byte>(), 0, keyBytes); destination[0] = (byte)s2kParameters.EncryptionAlgorithm; c.GenerateIV(); c.IV.CopyTo(destination.Slice(1)); int bytesWritten = 13 + ((c.BlockSize + 7) / 8); destination = destination.Slice(bytesWritten); c.Key = keyBytes.ToArray(); int checksum = 0; foreach (var b in source) { checksum += b; } for (int i = 0; i < 4; i++) { using var encryptor = new ZeroPaddedCryptoTransform(c.CreateEncryptor()); destination[0] = source[0]; destination[1] = source[1]; var mpInteger = MPInteger.ReadInteger(source, out int bytesConsumed).ToArray(); source = source.Slice(bytesConsumed); var data = encryptor.TransformFinalBlock(mpInteger, 0, mpInteger.Length); data.AsSpan().CopyTo(destination.Slice(2)); destination = destination.Slice(2 + data.Length); CryptographicOperations.ZeroMemory(mpInteger); if (i != 4) { c.IV = data.AsSpan(data.Length - (c.BlockSize / 8)).ToArray(); } } destination[0] = (byte)(checksum >> 8); destination[1] = (byte)(checksum); } else { var salt = new byte[8]; RandomNumberGenerator.Fill(salt); byte rawIterationCount = 0x60; int iterationCount = (16 + (rawIterationCount & 15)) << ((rawIterationCount >> 4) + 6); MakeKey(password, s2kParameters.HashAlgorithm, salt, iterationCount, keyBytes); destination[0] = (byte)s2kParameters.UsageTag; destination[1] = (byte)s2kParameters.EncryptionAlgorithm; destination[2] = 3; // Salted & iterated destination[3] = (byte)s2kParameters.HashAlgorithm; salt.CopyTo(destination.Slice(4)); destination[12] = rawIterationCount; c.GenerateIV(); c.IV.CopyTo(destination.Slice(13)); int bytesWritten = 13 + ((c.BlockSize + 7) / 8); destination = destination.Slice(bytesWritten); c.Key = keyBytes.ToArray(); using var encryptor = new ZeroPaddedCryptoTransform(c.CreateEncryptor()); byte[] checksumBytes; if (s2kParameters.UsageTag == S2kUsageTag.Sha1) { using var sha1 = IncrementalHash.CreateHash(HashAlgorithmName.SHA1); sha1.AppendData(source); checksumBytes = sha1.GetHashAndReset(); } else { int checksum = 0; foreach (var b in source) { checksum += b; } checksumBytes = new byte[] { (byte)(checksum >> 8), (byte)checksum }; } var decSource = new byte[source.Length + checksumBytes.Length]; source.CopyTo(decSource); checksumBytes.CopyTo(decSource, source.Length); var data = encryptor.TransformFinalBlock(decSource, 0, decSource.Length); data.AsSpan().CopyTo(destination); CryptographicOperations.ZeroMemory(data); CryptographicOperations.ZeroMemory(decSource); } }