public override bool TrySignHash(ReadOnlySpan <byte> hash, Span <byte> destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ArgumentNullException.ThrowIfNull(padding); ThrowIfDisposed(); bool pssPadding = padding.Mode switch { RSASignaturePaddingMode.Pss => true, RSASignaturePaddingMode.Pkcs1 => false, _ => throw new CryptographicException(SR.Cryptography_InvalidPaddingMode) }; SecKeyPair keys = GetKeys(); if (keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } int keySize = KeySize; int rsaSize = RsaPaddingProcessor.BytesRequiredForBitCount(keySize); if (!pssPadding) { Interop.AppleCrypto.PAL_HashAlgorithm palAlgId = PalAlgorithmFromAlgorithmName(hashAlgorithm, out int expectedSize); if (hash.Length != expectedSize) { // Windows: NTE_BAD_DATA ("Bad Data.") // OpenSSL: RSA_R_INVALID_MESSAGE_LENGTH ("invalid message length") throw new CryptographicException( SR.Format( SR.Cryptography_BadHashSize_ForAlgorithm, hash.Length, expectedSize, hashAlgorithm.Name)); } if (destination.Length < rsaSize) { bytesWritten = 0; return(false); } return(Interop.AppleCrypto.TryCreateSignature( keys.PrivateKey, hash, destination, palAlgId, Interop.AppleCrypto.PAL_SignatureAlgorithm.RsaPkcs1, out bytesWritten)); } Debug.Assert(padding.Mode == RSASignaturePaddingMode.Pss); if (destination.Length < rsaSize) { bytesWritten = 0; return(false); } byte[] rented = CryptoPool.Rent(rsaSize); Span <byte> buf = new Span <byte>(rented, 0, rsaSize); RsaPaddingProcessor.EncodePss(hashAlgorithm, hash, buf, keySize); try { return(Interop.AppleCrypto.TryRsaSignaturePrimitive(keys.PrivateKey, buf, destination, out bytesWritten)); } finally { CryptographicOperations.ZeroMemory(buf); CryptoPool.Return(rented, clearSize: 0); } }
private bool TrySignHash( ReadOnlySpan <byte> hash, Span <byte> destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, bool allocateSignature, out int bytesWritten, out byte[] signature) { Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name)); Debug.Assert(padding != null); signature = null; // Do not factor out getting _key.Value, since the key creation should not happen on // invalid padding modes. if (padding.Mode == RSASignaturePaddingMode.Pkcs1) { int algorithmNid = GetAlgorithmNid(hashAlgorithm); SafeRsaHandle rsa = _key.Value; int bytesRequired = Interop.Crypto.RsaSize(rsa); if (allocateSignature) { Debug.Assert(destination.Length == 0); signature = new byte[bytesRequired]; destination = signature; } if (destination.Length < bytesRequired) { bytesWritten = 0; return(false); } if (!Interop.Crypto.RsaSign(algorithmNid, hash, hash.Length, destination, out int signatureSize, rsa)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } Debug.Assert( signatureSize == bytesRequired, $"RSA_sign reported signatureSize was {signatureSize}, when {bytesRequired} was expected"); bytesWritten = signatureSize; return(true); } else if (padding.Mode == RSASignaturePaddingMode.Pss) { RsaPaddingProcessor processor = RsaPaddingProcessor.OpenProcessor(hashAlgorithm); SafeRsaHandle rsa = _key.Value; int bytesRequired = Interop.Crypto.RsaSize(rsa); if (allocateSignature) { Debug.Assert(destination.Length == 0); signature = new byte[bytesRequired]; destination = signature; } if (destination.Length < bytesRequired) { bytesWritten = 0; return(false); } byte[] pssRented = CryptoPool.Rent(bytesRequired); Span <byte> pssBytes = new Span <byte>(pssRented, 0, bytesRequired); processor.EncodePss(hash, pssBytes, KeySize); int ret = Interop.Crypto.RsaSignPrimitive(pssBytes, destination, rsa); CryptoPool.Return(pssRented, bytesRequired); CheckReturn(ret); Debug.Assert( ret == bytesRequired, $"RSA_private_encrypt returned {ret} when {bytesRequired} was expected"); bytesWritten = ret; return(true); } throw PaddingModeNotSupported(); }
private bool TrySignHash( ReadOnlySpan <byte> hash, Span <byte> destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, bool allocateSignature, out int bytesWritten, out byte[]?signature) { Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name)); Debug.Assert(padding != null); signature = null; if (padding == RSASignaturePadding.Pkcs1 && padding == RSASignaturePadding.Pss) { throw PaddingModeNotSupported(); } RsaPaddingProcessor processor = RsaPaddingProcessor.OpenProcessor(hashAlgorithm); SafeRsaHandle rsa = GetKey(); int bytesRequired = Interop.AndroidCrypto.RsaSize(rsa); if (allocateSignature) { Debug.Assert(destination.Length == 0); signature = new byte[bytesRequired]; destination = signature; } if (destination.Length < bytesRequired) { bytesWritten = 0; return(false); } byte[] encodedRented = CryptoPool.Rent(bytesRequired); Span <byte> encodedBytes = new Span <byte>(encodedRented, 0, bytesRequired); if (padding.Mode == RSASignaturePaddingMode.Pkcs1) { processor.PadPkcs1Signature(hash, encodedBytes); } else if (padding.Mode == RSASignaturePaddingMode.Pss) { processor.EncodePss(hash, encodedBytes, KeySize); } else { Debug.Fail("Padding mode should be checked prior to this point."); throw PaddingModeNotSupported(); } int ret = Interop.AndroidCrypto.RsaSignPrimitive(encodedBytes, destination, rsa); CryptoPool.Return(encodedRented, bytesRequired); CheckReturn(ret); Debug.Assert( ret == bytesRequired, $"RsaSignPrimitive returned {ret} when {bytesRequired} was expected"); bytesWritten = ret; return(true); }
public override bool TrySignHash(ReadOnlySpan <byte> hash, Span <byte> destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { if (string.IsNullOrEmpty(hashAlgorithm.Name)) { throw HashAlgorithmNameNullOrEmpty(); } if (padding == null) { throw new ArgumentNullException(nameof(padding)); } RsaPaddingProcessor processor = null; if (padding.Mode == RSASignaturePaddingMode.Pss) { processor = RsaPaddingProcessor.OpenProcessor(hashAlgorithm); } else if (padding != RSASignaturePadding.Pkcs1) { throw new CryptographicException(SR.Cryptography_InvalidPaddingMode); } SecKeyPair keys = GetKeys(); if (keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } int keySize = KeySize; int rsaSize = RsaPaddingProcessor.BytesRequiredForBitCount(keySize); if (processor == null) { Interop.AppleCrypto.PAL_HashAlgorithm palAlgId = PalAlgorithmFromAlgorithmName(hashAlgorithm, out int expectedSize); if (hash.Length != expectedSize) { // Windows: NTE_BAD_DATA ("Bad Data.") // OpenSSL: RSA_R_INVALID_MESSAGE_LENGTH ("invalid message length") throw new CryptographicException( SR.Format( SR.Cryptography_BadHashSize_ForAlgorithm, hash.Length, expectedSize, hashAlgorithm.Name)); } if (destination.Length < rsaSize) { bytesWritten = 0; return(false); } return(Interop.AppleCrypto.TryGenerateSignature( keys.PrivateKey, hash, destination, palAlgId, out bytesWritten)); } Debug.Assert(padding.Mode == RSASignaturePaddingMode.Pss); if (destination.Length < rsaSize) { bytesWritten = 0; return(false); } byte[] rented = ArrayPool <byte> .Shared.Rent(rsaSize); Span <byte> buf = new Span <byte>(rented, 0, rsaSize); processor.EncodePss(hash, buf, keySize); try { return(Interop.AppleCrypto.TryRsaSignaturePrimitive(keys.PrivateKey, buf, destination, out bytesWritten)); } finally { CryptographicOperations.ZeroMemory(buf); ArrayPool <byte> .Shared.Return(rented); } }