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 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 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 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 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); } }
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); } }