public override byte[] CreateSignature(byte[] rgbHash) { if (rgbHash == null) { throw new ArgumentNullException(nameof(rgbHash)); } SafeDsaHandle key = GetKey(); int signatureSize = Interop.Crypto.DsaEncodedSignatureSize(key); int signatureFieldSize = Interop.Crypto.DsaSignatureFieldSize(key) * BitsPerByte; Span <byte> signDestination = stackalloc byte[SignatureStackBufSize]; ReadOnlySpan <byte> derSignature = SignHash(rgbHash, signDestination, signatureSize, key); return(AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, signatureFieldSize)); }
public override bool VerifySignature(ReadOnlySpan <byte> rgbHash, ReadOnlySpan <byte> rgbSignature) { SafeDsaHandle key = _key.Value; int expectedSignatureBytes = Interop.Crypto.DsaSignatureFieldSize(key) * 2; if (rgbSignature.Length != expectedSignatureBytes) { // The input isn't of the right length (assuming no DER), so we can't sensibly re-encode it with DER. return(false); } byte[] openSslFormat = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(rgbSignature); return(Interop.Crypto.DsaVerify(key, rgbHash, rgbHash.Length, openSslFormat, openSslFormat.Length)); }
private UniversalCryptoTransform CreateEphemeralCryptoTransformCore(byte[] key, byte[]?iv, bool encrypting, PaddingMode padding, CipherMode mode, int feedbackSizeInBits) { int blockSizeInBytes = AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize); SafeAlgorithmHandle algorithmModeHandle = _outer.GetEphemeralModeHandle(mode, feedbackSizeInBits); BasicSymmetricCipher cipher = new BasicSymmetricCipherBCrypt( algorithmModeHandle, mode, blockSizeInBytes, _outer.GetPaddingSize(mode, feedbackSizeInBits), key, ownsParentHandle: false, iv, encrypting); return(UniversalCryptoTransform.Create(padding, cipher, encrypting)); }
/// <summary> /// Gets the largest size, in bytes, for a signature produced by this key in the indicated format. /// </summary> /// <param name="signatureFormat">The encoding format for a signature.</param> /// <returns> /// The largest size, in bytes, for a signature produced by this key in the indicated format. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="signatureFormat"/> is not a known format. /// </exception> public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) { DSAParameters dsaParameters = ExportParameters(false); int qLength = dsaParameters.Q !.Length; switch (signatureFormat) { case DSASignatureFormat.IeeeP1363FixedFieldConcatenation: return(qLength * 2); case DSASignatureFormat.Rfc3279DerSequence: return(AsymmetricAlgorithmHelpers.GetMaxDerSignatureSize(fieldSizeBits: qLength * 8)); default: throw new ArgumentOutOfRangeException(nameof(signatureFormat)); } }
private static bool TryExportDataKeyParameters( SecKeyPair keys, bool includePrivateParameters, ref ECParameters ecParameters) { if (includePrivateParameters && keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); } bool gotKeyBlob = Interop.AppleCrypto.TrySecKeyCopyExternalRepresentation( includePrivateParameters ? keys.PrivateKey ! : keys.PublicKey, out byte[] keyBlob); if (!gotKeyBlob) { return(false); } try { AsymmetricAlgorithmHelpers.DecodeFromUncompressedAnsiX963Key( keyBlob, includePrivateParameters, out ecParameters); switch (GetKeySize(keys)) { case 256: ecParameters.Curve = ECCurve.NamedCurves.nistP256; break; case 384: ecParameters.Curve = ECCurve.NamedCurves.nistP384; break; case 521: ecParameters.Curve = ECCurve.NamedCurves.nistP521; break; default: Debug.Fail("Unsupported curve"); throw new CryptographicException(); } return(true); } finally { CryptographicOperations.ZeroMemory(keyBlob); } }
public override byte[] SignHash(byte[] hash) { if (hash == null) { throw new ArgumentNullException(nameof(hash)); } ThrowIfDisposed(); SafeEcKeyHandle key = _key.Value; int signatureLength = Interop.Crypto.EcDsaSize(key); Span <byte> signDestination = stackalloc byte[SignatureStackBufSize]; ReadOnlySpan <byte> derSignature = SignHash(hash, signDestination, signatureLength, key); byte[] converted = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, KeySize); return(converted); }
private UniversalCryptoTransform CreatePersistedCryptoTransformCore(Func <CngKey> cngKeyFactory, byte[]?iv, bool encrypting, PaddingMode padding, CipherMode mode, int feedbackSizeInBits) { // note: iv is guaranteed to be cloned before this method, so no need to clone it again ValidateFeedbackSize(mode, feedbackSizeInBits); Debug.Assert(mode == CipherMode.CFB ? feedbackSizeInBits == 8 : true); int blockSizeInBytes = AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize); BasicSymmetricCipher cipher = new BasicSymmetricCipherNCrypt( cngKeyFactory, mode, blockSizeInBytes, iv, encrypting, _outer.GetPaddingSize(mode, feedbackSizeInBits)); return(UniversalCryptoTransform.Create(padding, cipher, encrypting)); }
public override bool VerifyHash(byte[] hash, byte[] signature) { if (hash == null) { throw new ArgumentNullException(nameof(hash)); } if (signature == null) { throw new ArgumentNullException(nameof(signature)); } byte[] derFormatSignature = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); return(Interop.AppleCrypto.VerifySignature( GetKeys().PublicKey, hash, derFormatSignature)); }
public override bool VerifyHash(ReadOnlySpan <byte> hash, ReadOnlySpan <byte> signature) { // The signature format for .NET is r.Concat(s). Each of r and s are of length BitsToBytes(KeySize), even // when they would have leading zeroes. If it's the correct size, then we need to encode it from // r.Concat(s) to SEQUENCE(INTEGER(r), INTEGER(s)), because that's the format that OpenSSL expects. int expectedBytes = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); if (signature.Length != expectedBytes) { // The input isn't of the right length, so we can't sensibly re-encode it. return(false); } return(Interop.AppleCrypto.VerifySignature( GetKeys().PublicKey, hash, AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature))); }
/// <summary> /// Attempts to create the DSA signature for the specified hash value in the indicated format /// into the provided buffer. /// </summary> /// <param name="hash">The hash value to sign.</param> /// <param name="destination">The buffer to receive the signature.</param> /// <param name="signatureFormat">The encoding format to use for the signature.</param> /// <param name="bytesWritten"> /// When this method returns, contains a value that indicates the number of bytes written to /// <paramref name="destination"/>. This parameter is treated as uninitialized. /// </param> /// <returns> /// <see langword="true"/> if <paramref name="destination"/> is big enough to receive the signature; /// otherwise, <see langword="false"/>. /// </returns> /// <exception cref="CryptographicException"> /// An error occurred in the signing operation. /// </exception> protected virtual bool TryCreateSignatureCore( ReadOnlySpan <byte> hash, Span <byte> destination, DSASignatureFormat signatureFormat, out int bytesWritten) { // This method is expected to be overriden with better implementation // The only available implementation here is abstract method, use it byte[] sig = CreateSignature(hash.ToArray()); if (signatureFormat != DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { sig = AsymmetricAlgorithmHelpers.ConvertFromIeeeP1363Signature(sig, signatureFormat); } return(Helpers.TryCopyToDestination(sig, destination, out bytesWritten)); }
/// <summary> /// Computes the hash value of the specified data and signs it using the specified signature format. /// </summary> /// <param name="data">The data to sign.</param> /// <param name="hashAlgorithm">The hash algorithm to use to create the hash value.</param> /// <param name="signatureFormat">The encoding format to use for the signature.</param> /// <returns> /// The DSA signature for the specified data. /// </returns> /// <exception cref="CryptographicException"> /// An error occurred in the hashing or signing operation. /// </exception> protected virtual byte[] SignDataCore( ReadOnlySpan <byte> data, HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat) { Span <byte> signature = stackalloc byte[SignatureStackSize]; if (TrySignDataCore(data, signature, hashAlgorithm, signatureFormat, out int bytesWritten)) { return(signature.Slice(0, bytesWritten).ToArray()); } // If that didn't work, fall back on older approaches. byte[] hash = HashSpanToArray(data, hashAlgorithm); byte[] sig = CreateSignature(hash); return(AsymmetricAlgorithmHelpers.ConvertFromIeeeP1363Signature(sig, signatureFormat)); }
private UniversalCryptoTransform CreateCryptoTransform(byte[] rgbKey, byte[]?rgbIV, bool encrypting, PaddingMode padding, CipherMode mode, int feedbackSizeInBits) { ArgumentNullException.ThrowIfNull(rgbKey); ValidateFeedbackSize(mode, feedbackSizeInBits); byte[] key = CopyAndValidateKey(rgbKey); if (rgbIV != null && rgbIV.Length != AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize)) { throw new ArgumentException(SR.Cryptography_InvalidIVSize, nameof(rgbIV)); } // CloneByteArray is null-preserving. So even when GetCipherIv returns null the iv variable // is correct, and detached from the input parameter. byte[]? iv = mode.GetCipherIv(rgbIV).CloneByteArray(); return(CreateEphemeralCryptoTransformCore(key, iv, encrypting, padding, mode, feedbackSizeInBits)); }
public override bool TryCreateSignature(ReadOnlySpan <byte> source, Span <byte> destination, out int bytesWritten) { byte[] converted; SafeDsaHandle key = _key.Value; int signatureSize = Interop.Crypto.DsaEncodedSignatureSize(key); byte[] signature = ArrayPool <byte> .Shared.Rent(signatureSize); try { bool success = Interop.Crypto.DsaSign(key, source, source.Length, new Span <byte>(signature, 0, signatureSize), out signatureSize); if (!success) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } Debug.Assert( signatureSize <= signature.Length, "DSA_sign reported an unexpected signature size", "DSA_sign reported signatureSize was {0}, when <= {1} was expected", signatureSize, signature.Length); int signatureFieldSize = Interop.Crypto.DsaSignatureFieldSize(key) * BitsPerByte; converted = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(signature, 0, signatureSize, signatureFieldSize); } finally { Array.Clear(signature, 0, signatureSize); ArrayPool <byte> .Shared.Return(signature); } if (converted.Length <= destination.Length) { new ReadOnlySpan <byte>(converted).CopyTo(destination); bytesWritten = converted.Length; return(true); } else { bytesWritten = 0; return(false); } }
public override bool VerifyHash(ReadOnlySpan <byte> hash, ReadOnlySpan <byte> signature) { // The signature format for .NET is r.Concat(s). Each of r and s are of length BitsToBytes(KeySize), even // when they would have leading zeroes. If it's the correct size, then we need to encode it from // r.Concat(s) to SEQUENCE(INTEGER(r), INTEGER(s)), because that's the format that OpenSSL expects. int expectedBytes = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); if (signature.Length != expectedBytes) { // The input isn't of the right length, so we can't sensibly re-encode it. return(false); } byte[] openSslFormat = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); SafeEcKeyHandle key = _key.Value; int verifyResult = Interop.Crypto.EcDsaVerify(hash, hash.Length, openSslFormat, openSslFormat.Length, key); return(verifyResult == 1); }
private ILiteSymmetricCipher CreatePersistedLiteSymmetricCipher( Func <CngKey> cngKeyFactory, ReadOnlySpan <byte> iv, bool encrypting, PaddingMode padding, CipherMode mode, int feedbackSizeInBits) { ValidateFeedbackSize(mode, feedbackSizeInBits); Debug.Assert(mode == CipherMode.CFB ? feedbackSizeInBits == 8 : true); int blockSizeInBytes = AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize); return(new BasicSymmetricCipherLiteNCrypt( cngKeyFactory, mode, blockSizeInBytes, iv, encrypting, _outer.GetPaddingSize(mode, feedbackSizeInBits))); }
public override byte[] SignHash(byte[] hash) { if (hash == null) { throw new ArgumentNullException(nameof(hash)); } SafeEcKeyHandle key = _key.Value; int signatureLength = Interop.Crypto.EcDsaSize(key); byte[] signature = new byte[signatureLength]; if (!Interop.Crypto.EcDsaSign(hash, hash.Length, signature, ref signatureLength, key)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } byte[] converted = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(signature, 0, signatureLength, KeySize); return(converted); }
public override byte[] SignHash(byte[] hash) { if (hash == null) { throw new ArgumentNullException(nameof(hash)); } SecKeyPair keys = GetKeys(); if (keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } byte[] derFormatSignature = Interop.AppleCrypto.GenerateSignature(keys.PrivateKey, hash); byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363( derFormatSignature.AsSpan(0, derFormatSignature.Length), KeySize); return(ieeeFormatSignature); }
public override byte[] SignHash(byte[] hash) { ArgumentNullException.ThrowIfNull(hash); SecKeyPair keys = GetKeys(); if (keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } byte[] derFormatSignature = Interop.AppleCrypto.CreateSignature( keys.PrivateKey, hash, Interop.AppleCrypto.PAL_HashAlgorithm.Unknown, Interop.AppleCrypto.PAL_SignatureAlgorithm.EC); byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363( derFormatSignature.AsSpan(0, derFormatSignature.Length), KeySize); return(ieeeFormatSignature); }
private UniversalCryptoTransform CreateCryptoTransform(byte[] rgbKey, byte[]?rgbIV, bool encrypting, PaddingMode padding, CipherMode mode, int feedbackSizeInBits) { if (rgbKey == null) { throw new ArgumentNullException(nameof(rgbKey)); } ValidateFeedbackSize(mode, feedbackSizeInBits); byte[] key = rgbKey.CloneByteArray(); long keySize = key.Length * (long)BitsPerByte; if (keySize > int.MaxValue || !((int)keySize).IsLegalSize(_outer.LegalKeySizes)) { throw new ArgumentException(SR.Cryptography_InvalidKeySize, nameof(rgbKey)); } if (_outer.IsWeakKey(key)) { throw new CryptographicException( SR.Format( SR.Cryptography_InvalidKey_Weak, _outer.GetNCryptAlgorithmIdentifier())); } if (rgbIV != null && rgbIV.Length != AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize)) { throw new ArgumentException(SR.Cryptography_InvalidIVSize, nameof(rgbIV)); } // CloneByteArray is null-preserving. So even when GetCipherIv returns null the iv variable // is correct, and detached from the input parameter. byte[]? iv = mode.GetCipherIv(rgbIV).CloneByteArray(); key = _outer.PreprocessKey(key); return(CreateEphemeralCryptoTransformCore(key, iv, encrypting, padding, mode, feedbackSizeInBits)); }
public override unsafe bool TryCreateSignature(ReadOnlySpan <byte> hash, Span <byte> destination, out int bytesWritten) #endif { Span <byte> stackBuf = stackalloc byte[WindowsMaxQSize]; ReadOnlySpan <byte> source = AdjustHashSizeIfNecessary(hash, stackBuf); using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { if (!CngCommon.TrySignHash(keyHandle, source, destination, AsymmetricPaddingMode.None, null, out bytesWritten)) { bytesWritten = 0; return(false); } } #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { return(true); } if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence) { Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); throw new CryptographicException( SR.Cryptography_UnknownSignatureFormat, signatureFormat.ToString()); } return(AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer( destination.Slice(0, bytesWritten), destination, out bytesWritten)); #else return(true); #endif }
public override byte[] CreateSignature(byte[] hash) { if (hash == null) throw new ArgumentNullException(nameof(hash)); SecKeyPair keys = GetKeys(); if (keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } byte[] derFormatSignature = Interop.AppleCrypto.GenerateSignature(keys.PrivateKey, hash); // Since the AppleCrypto implementation is limited to FIPS 186-2, signature field sizes // are always 160 bits / 20 bytes (the size of SHA-1, and the only legal length for Q). byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363( derFormatSignature, 0, derFormatSignature.Length, fieldSizeBits: 160); return ieeeFormatSignature; }
public override byte[] CreateSignature(byte[] rgbHash) { if (rgbHash == null) { throw new ArgumentNullException(nameof(rgbHash)); } SafeDsaHandle key = _key.Value; int signatureSize = Interop.Crypto.DsaEncodedSignatureSize(key); byte[] signature = ArrayPool <byte> .Shared.Rent(signatureSize); try { bool success = Interop.Crypto.DsaSign(key, rgbHash, rgbHash.Length, new Span <byte>(signature, 0, signatureSize), out signatureSize); if (!success) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } Debug.Assert( signatureSize <= signature.Length, "DSA_sign reported an unexpected signature size", "DSA_sign reported signatureSize was {0}, when <= {1} was expected", signatureSize, signature.Length); int signatureFieldSize = Interop.Crypto.DsaSignatureFieldSize(key) * BitsPerByte; return(AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(signature, 0, signatureSize, signatureFieldSize)); } finally { Array.Clear(signature, 0, signatureSize); ArrayPool <byte> .Shared.Return(signature); } }
public override bool TrySignHash(ReadOnlySpan <byte> source, Span <byte> destination, out int bytesWritten) { SafeEcKeyHandle key = _key.Value; byte[] converted; int signatureLength = Interop.Crypto.EcDsaSize(key); byte[] signature = ArrayPool <byte> .Shared.Rent(signatureLength); try { if (!Interop.Crypto.EcDsaSign(source, source.Length, new Span <byte>(signature, 0, signatureLength), ref signatureLength, key)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } converted = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(signature, 0, signatureLength, KeySize); } finally { Array.Clear(signature, 0, signatureLength); ArrayPool <byte> .Shared.Return(signature); } if (converted.Length <= destination.Length) { new ReadOnlySpan <byte>(converted).CopyTo(destination); bytesWritten = converted.Length; return(true); } else { bytesWritten = 0; return(false); } }
protected override bool TryHashData(ReadOnlySpan <byte> data, Span <byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten);
protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm);
protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) => AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm);
public override bool VerifyHash(ReadOnlySpan <byte> hash, ReadOnlySpan <byte> signature) => Interop.AppleCrypto.VerifySignature( GetKeys().PublicKey, hash, AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature));
/// <summary> /// Get the secret agreement generated between two parties /// </summary> private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash?hasher) { Debug.Assert(otherPartyPublicKey != null); // Ensure that this ECDH object contains a private key by attempting a parameter export // which will throw an OpenSslCryptoException if no private key is available ECParameters thisKeyExplicit = ExportExplicitParameters(true); bool thisIsNamed = Interop.AndroidCrypto.EcKeyHasCurveName(_key.Value); ECDiffieHellmanAndroidPublicKey?otherKey = otherPartyPublicKey as ECDiffieHellmanAndroidPublicKey; bool disposeOtherKey = false; if (otherKey == null) { disposeOtherKey = true; ECParameters otherParameters = thisIsNamed ? otherPartyPublicKey.ExportParameters() : otherPartyPublicKey.ExportExplicitParameters(); otherKey = new ECDiffieHellmanAndroidPublicKey(otherParameters); } bool otherIsNamed = otherKey.HasCurveName; SafeEcKeyHandle?ourKey = null; SafeEcKeyHandle?theirKey = null; byte[]? rented = null; // Calculate secretLength in bytes. int secretLength = AsymmetricAlgorithmHelpers.BitsToBytes(KeySize); try { if (otherKey.KeySize != KeySize) { throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey)); } if (otherIsNamed == thisIsNamed) { ourKey = _key.UpRefKeyHandle(); theirKey = otherKey.DuplicateKeyHandle(); } else if (otherIsNamed) { ourKey = _key.UpRefKeyHandle(); using (ECAndroid tmp = new ECAndroid(otherKey.ExportExplicitParameters())) { theirKey = tmp.UpRefKeyHandle(); } } else { using (ECAndroid tmp = new ECAndroid(thisKeyExplicit)) { ourKey = tmp.UpRefKeyHandle(); } theirKey = otherKey.DuplicateKeyHandle(); } // Indicate that secret can hold stackallocs from nested scopes Span <byte> secret = stackalloc byte[0]; // Arbitrary limit. But it covers secp521r1, which is the biggest common case. const int StackAllocMax = 66; if (secretLength > StackAllocMax) { rented = CryptoPool.Rent(secretLength); secret = new Span <byte>(rented, 0, secretLength); } else { secret = stackalloc byte[secretLength]; } if (!Interop.AndroidCrypto.EcdhDeriveKey(ourKey, theirKey, secret, out int usedBufferLength)) { throw new CryptographicException(); } Debug.Assert(secretLength == usedBufferLength, $"Expected secret length {secretLength} does not match actual secret length {usedBufferLength}."); if (hasher == null) { return(secret.ToArray()); } else { hasher.AppendData(secret); return(null); } } finally { theirKey?.Dispose(); ourKey?.Dispose(); if (disposeOtherKey) { otherKey.Dispose(); } if (rented != null) { CryptoPool.Return(rented, secretLength); } } }
public void GenerateIV() { byte[] iv = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize)); _outer.IV = iv; }
public void GenerateKey() { byte[] key = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BaseKeySize)); SetKey(key); }