Ejemplo n.º 1
0
        public void Rfc23279TrySignDataUnderMax()
        {
            KeyDescription keyDescription = GetKey();
            ECDsa          key            = (ECDsa)keyDescription.Key;

            const DSASignatureFormat SignatureFormat = DSASignatureFormat.Rfc3279DerSequence;
            const int         RetryCount             = 10;
            HashAlgorithmName hashAlgorithm          = HashAlgorithmName.SHA1;

            int expectedSize = GetExpectedSize(keyDescription.FieldSizeInBits);
            int maxSize      = key.GetMaxSignatureSize(DSASignatureFormat.Rfc3279DerSequence);

            Assert.True(expectedSize < maxSize, "expectedSize < maxSize");
            byte[] signature = new byte[expectedSize];

            for (int i = 0; i < RetryCount; i++)
            {
                if (key.TrySignData(Array.Empty <byte>(), signature, hashAlgorithm, SignatureFormat, out int written))
                {
                    return;
                }

                Assert.Equal(0, written);
            }

            Assert.True(false, $"TrySignData eventually succeeds with a {expectedSize}/{maxSize}-byte destination");
        }
Ejemplo n.º 2
0
        public void Rfc23279TrySignHashUnderMax()
        {
            KeyDescription keyDescription = GetKey();
            ECDsa          key            = (ECDsa)keyDescription.Key;

            const DSASignatureFormat SignatureFormat = DSASignatureFormat.Rfc3279DerSequence;
            const int RetryCount = 10;

            byte[] hash = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

            int expectedSize = GetExpectedSize(keyDescription.FieldSizeInBits);
            int maxSize      = key.GetMaxSignatureSize(DSASignatureFormat.Rfc3279DerSequence);

            Assert.True(expectedSize < maxSize, "expectedSize < maxSize");
            byte[] signature = new byte[expectedSize];

            for (int i = 0; i < RetryCount; i++)
            {
                if (key.TrySignHash(hash, signature, SignatureFormat, out int written))
                {
                    return;
                }

                Assert.Equal(0, written);
            }

            Assert.True(false, $"TrySignHash eventually succeeds with a {expectedSize}/{maxSize}-byte destination");
        }
Ejemplo n.º 3
0
        protected override byte[] SignHashCore(ReadOnlySpan <byte> hash, DSASignatureFormat signatureFormat)
        {
            if (this.publicKey == null)
            {
                CreateKeys();
            }
            if (this.privateKey == null)
            {
                throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
            }

            byte[] signature = NSec.Cryptography.SignatureAlgorithm.Ed25519.Sign(this.privateKey, hash).ToArray();

            if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
            {
                var writer = new AsnWriter(AsnEncodingRules.DER);
                using (var sequence = writer.PushSequence())
                {
                    writer.WriteIntegerUnsigned(signature.AsSpan(0, 32));
                    writer.WriteIntegerUnsigned(signature.AsSpan(32));
                }
                signature = writer.Encode();
            }

            return(signature);
        }
Ejemplo n.º 4
0
        protected override bool VerifySignatureCore(
            ReadOnlySpan <byte> hash,
            ReadOnlySpan <byte> signature,
            DSASignatureFormat signatureFormat)
        {
            Span <byte>         stackBuf = stackalloc byte[WindowsMaxQSize];
            ReadOnlySpan <byte> source   = AdjustHashSizeIfNecessary(hash, stackBuf);

            if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
            {
                // source.Length is the field size, in bytes, so just convert to bits.
                int fieldSizeBits = source.Length * 8;
                signature = this.ConvertSignatureToIeeeP1363(signatureFormat, signature, fieldSizeBits);
            }
            else if (signatureFormat != DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
            {
                Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
                throw new CryptographicException(
                          SR.Cryptography_UnknownSignatureFormat,
                          signatureFormat.ToString());
            }

            using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
            {
                unsafe
                {
                    return(CngCommon.VerifyHash(keyHandle, source, signature, AsymmetricPaddingMode.None, null));
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        ///   Verifies that a digital signature is valid for the provided data.
        /// </summary>
        /// <param name="data">The signed data.</param>
        /// <param name="signature">The signature to verify.</param>
        /// <param name="hashAlgorithm">The hash algorithm used to hash the data for the verification process.</param>
        /// <param name="signatureFormat">The encoding format for <paramref name="signature"/>.</param>
        /// <returns>
        ///   <see langword="true"/> if the digital signature is valid for the provided data; otherwise, <see langword="false"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///   <paramref name="data"/> or <paramref name="signature"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="signatureFormat"/> is not a known format.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="hashAlgorithm"/> has a <see langword="null"/> or empty <see cref="HashAlgorithmName.Name"/>.
        /// </exception>
        /// <exception cref="CryptographicException">
        ///   An error occurred in the hashing or verification operation.
        /// </exception>
        public bool VerifyData(
            Stream data,
            byte[] signature,
            HashAlgorithmName hashAlgorithm,
            DSASignatureFormat signatureFormat)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (signature == null)
            {
                throw new ArgumentNullException(nameof(signature));
            }
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
            {
                throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm));
            }
            if (!signatureFormat.IsKnownValue())
            {
                throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat);
            }

            return(VerifyDataCore(data, signature, hashAlgorithm, signatureFormat));
        }
Ejemplo n.º 6
0
            protected override bool VerifySignatureCore(
                ReadOnlySpan <byte> hash,
                ReadOnlySpan <byte> signature,
                DSASignatureFormat signatureFormat)
            {
                SafeDsaHandle key = GetKey();

                if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
                {
                    int expectedSignatureBytes = Interop.AndroidCrypto.DsaSignatureFieldSize(key) * 2;
                    if (signature.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);
                    }

                    signature = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature);
                }
                else if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence)
                {
                    Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
                    throw new CryptographicException(
                              SR.Cryptography_UnknownSignatureFormat,
                              signatureFormat.ToString());
                }
                return(Interop.AndroidCrypto.DsaVerify(key, hash, signature));
            }
Ejemplo n.º 7
0
        public void Rfc3279SignatureValidatesLength()
        {
            KeyDescription           key             = GetKey();
            HashAlgorithmName        hashAlgorithm   = HashAlgorithmName.SHA1;
            const DSASignatureFormat SignatureFormat = DSASignatureFormat.Rfc3279DerSequence;

            byte[] hash        = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
            byte[] signature   = SignHash(key, hash, SignatureFormat);
            byte[] rightPadded = signature.Concat(Enumerable.Repeat((byte)0, 4)).ToArray();

            Assert.True(
                VerifyHash(key, hash, signature, SignatureFormat),
                "VerifyHash with the unmodified signature");

            Assert.False(
                VerifyHash(key, hash, rightPadded, SignatureFormat),
                "VerifyHash with the right-padded signature");

            signature   = SignData(key, hash, hashAlgorithm, SignatureFormat);
            rightPadded = signature.Concat(Enumerable.Repeat((byte)0, 4)).ToArray();

            Assert.True(
                VerifyData(key, hash, signature, hashAlgorithm, SignatureFormat),
                "VerifyData with the unmodified signature");

            Assert.False(
                VerifyData(key, hash, rightPadded, hashAlgorithm, SignatureFormat),
                "VerifyData with the right-padded signature");
        }
Ejemplo n.º 8
0
        protected override unsafe bool TrySignHashCore(
            ReadOnlySpan <byte> hash,
            Span <byte> destination,
            DSASignatureFormat signatureFormat,
            out int bytesWritten)
        {
            using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
            {
                if (!keyHandle.TrySignHash(hash, destination, AsymmetricPaddingMode.None, null, out bytesWritten))
                {
                    bytesWritten = 0;
                    return(false);
                }
            }

            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));
        }
        public void Rfc23279TrySignDataUnderMax()
        {
            KeyDescription keyDescription = GetKey();
            ECDsa          key            = (ECDsa)keyDescription.Key;

            const DSASignatureFormat SignatureFormat = DSASignatureFormat.Rfc3279DerSequence;
            // Make secp521r1 (7/16 chance of being smaller) and mod-8 keys (3/4 chance of being smaller)
            // have the same 1-in-a-billion chance of failure.
            int retryCount = keyDescription.FieldSizeInBits % 8 == 1 ? 36 : 15;
            HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA1;

            int expectedSize = GetExpectedSize(keyDescription.FieldSizeInBits);
            int maxSize      = key.GetMaxSignatureSize(DSASignatureFormat.Rfc3279DerSequence);

            Assert.True(expectedSize < maxSize, "expectedSize < maxSize");
            byte[] signature = new byte[expectedSize];

            for (int i = 0; i < retryCount; i++)
            {
                if (key.TrySignData(Array.Empty <byte>(), signature, hashAlgorithm, SignatureFormat, out int written))
                {
                    return;
                }

                Assert.Equal(0, written);
            }

            Assert.True(false, $"TrySignData eventually succeeds with a {expectedSize}/{maxSize}-byte destination");
        }
Ejemplo n.º 10
0
 protected override byte[] SignHash(
     KeyDescription key,
     byte[] hash,
     DSASignatureFormat signatureFormat)
 {
     return(((ECDsa)key.Key).SignHash(hash, signatureFormat));
 }
Ejemplo n.º 11
0
        protected override byte[] SignData(
            KeyDescription key,
            byte[] data,
            HashAlgorithmName hashAlgorithm,
            DSASignatureFormat signatureFormat)
        {
            ECDsa dsa = (ECDsa)key.Key;

            byte[] predictedMax = new byte[dsa.GetMaxSignatureSize(signatureFormat)];

            Assert.True(
                dsa.TrySignData(data, predictedMax, hashAlgorithm, signatureFormat, out int written),
                "TrySignData with a GetMaxSignatureSize buffer");

            if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
            {
                // GetMaxSignatureSize should be exactly accurate for P1363.
                Assert.Equal(predictedMax.Length, written);
            }

            if (written == predictedMax.Length)
            {
                return(predictedMax);
            }

            return(predictedMax.AsSpan(0, written).ToArray());
        }
Ejemplo n.º 12
0
        public void Rfc23279TrySignHashUnderMax()
        {
            KeyDescription keyDescription = GetKey();
            ECDsa          key            = (ECDsa)keyDescription.Key;

            const DSASignatureFormat SignatureFormat = DSASignatureFormat.Rfc3279DerSequence;
            // Make secp521r1 (7/16 chance of being smaller) and mod-8 keys (3/4 chance of being smaller)
            // have the same 1-in-a-billion chance of failure.
            int retryCount = keyDescription.FieldSizeInBits % 8 == 1 ? 36 : 15;

            byte[] hash = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

            int expectedSize = GetExpectedSize(keyDescription.FieldSizeInBits);
            int maxSize      = key.GetMaxSignatureSize(DSASignatureFormat.Rfc3279DerSequence);

            Assert.True(expectedSize < maxSize, "expectedSize < maxSize");
            byte[] signature = new byte[expectedSize];

            for (int i = 0; i < retryCount; i++)
            {
                if (key.TrySignHash(hash, signature, SignatureFormat, out int written))
                {
                    return;
                }

                Assert.Equal(0, written);
            }

            Assert.True(false, $"TrySignHash eventually succeeds with a {expectedSize}/{maxSize}-byte destination");
        }
Ejemplo n.º 13
0
        /// <summary>
        ///   Verifies that a digital signature is valid for the provided data.
        /// </summary>
        /// <param name="data">An array that contains the signed data.</param>
        /// <param name="offset">The starting index of the signed portion of <paramref name="data"/>.</param>
        /// <param name="count">The number of bytes in <paramref name="data"/> that were signed.</param>
        /// <param name="signature">The signature to verify.</param>
        /// <param name="hashAlgorithm">The hash algorithm used to hash the data for the verification process.</param>
        /// <param name="signatureFormat">The encoding format for <paramref name="signature"/>.</param>
        /// <returns>
        ///   <see langword="true"/> if the digital signature is valid for the provided data; otherwise, <see langword="false"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///   <paramref name="data"/> or <paramref name="signature"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="signatureFormat"/> is not a known format.
        ///
        ///   -or-
        ///
        ///   <paramref name="offset" /> is less than zero.
        ///
        ///   -or-
        ///
        ///   <paramref name="count" /> is less than zero.
        ///
        ///   -or-
        ///
        ///   <paramref name="offset" /> + <paramref name="count"/> - 1 results in an index that is
        ///   beyond the upper bound of <paramref name="data"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="hashAlgorithm"/> has a <see langword="null"/> or empty <see cref="HashAlgorithmName.Name"/>.
        /// </exception>
        /// <exception cref="CryptographicException">
        ///   An error occurred in the hashing or verification operation.
        /// </exception>
        public bool VerifyData(
            byte[] data,
            int offset,
            int count,
            byte[] signature,
            HashAlgorithmName hashAlgorithm,
            DSASignatureFormat signatureFormat)
        {
            ArgumentNullException.ThrowIfNull(data);
            if (offset < 0 || offset > data.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (count < 0 || count > data.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }
            ArgumentNullException.ThrowIfNull(signature);
            ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
            if (!signatureFormat.IsKnownValue())
            {
                throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat);
            }

            return(VerifyDataCore(
                       new ReadOnlySpan <byte>(data, offset, count),
                       signature,
                       hashAlgorithm,
                       signatureFormat));
        }
Ejemplo n.º 14
0
        /// <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)
        {
            int fieldSizeBits = KeySize;

            if (fieldSizeBits == 0)
            {
                // Coerce the key/key-size into existence
                ExportParameters(false);

                fieldSizeBits = KeySize;

                // This implementation of ECDsa doesn't set KeySize, we can't
                if (fieldSizeBits == 0)
                {
                    throw new NotSupportedException(SR.Cryptography_InvalidKeySize);
                }
            }

            switch (signatureFormat)
            {
            case DSASignatureFormat.IeeeP1363FixedFieldConcatenation:
                return(AsymmetricAlgorithmHelpers.BitsToBytes(fieldSizeBits) * 2);

            case DSASignatureFormat.Rfc3279DerSequence:
                return(AsymmetricAlgorithmHelpers.GetMaxDerSignatureSize(fieldSizeBits));

            default:
                throw new ArgumentOutOfRangeException(nameof(signatureFormat));
            }
        }
Ejemplo n.º 15
0
        /// <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="offset">The offset into <paramref name="data"/> at which to begin hashing.</param>
        /// <param name="count">The number of bytes to read from <paramref name="data"/>.</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 ECDSA signature for the specified data.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///   <paramref name="data"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="signatureFormat"/> is not a known format.
        ///
        ///   -or-
        ///
        ///   <paramref name="offset" /> is less than zero.
        ///
        ///   -or-
        ///
        ///   <paramref name="count" /> is less than zero.
        ///
        ///   -or-
        ///
        ///   <paramref name="offset" /> + <paramref name="count"/> - 1 results in an index that is
        ///   beyond the upper bound of <paramref name="data"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="hashAlgorithm"/> has a <see langword="null"/> or empty <see cref="HashAlgorithmName.Name"/>.
        /// </exception>
        /// <exception cref="CryptographicException">
        ///   An error occurred in the hashing or signing operation.
        /// </exception>
        public byte[] SignData(
            byte[] data,
            int offset,
            int count,
            HashAlgorithmName hashAlgorithm,
            DSASignatureFormat signatureFormat)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (offset < 0 || offset > data.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (count < 0 || count > data.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
            {
                throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm));
            }
            if (!signatureFormat.IsKnownValue())
            {
                throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat);
            }

            return(SignDataCore(new ReadOnlySpan <byte>(data, offset, count), hashAlgorithm, signatureFormat));
        }
Ejemplo n.º 16
0
        private static void CheckLength(KeyDescription key, byte[] signature, DSASignatureFormat signatureFormat)
        {
            int fieldSizeBytes = (key.FieldSizeInBits + 7) / 8;

            switch (signatureFormat)
            {
            case DSASignatureFormat.IeeeP1363FixedFieldConcatenation:

                Assert.Equal(2 * fieldSizeBytes, signature.Length);
                break;

            case DSASignatureFormat.Rfc3279DerSequence:
            {
                // SEQUENCE(INTEGER, INTEGER) has a minimum length of 8 (30 06 02 01 00 02 01 00)
                // The maximum length is a bit more complicated:
                int elemSize    = fieldSizeBytes + 1;
                int integerMax  = 2 + GetDerLengthLength(elemSize) + elemSize;
                int integersMax = 2 * integerMax;
                int sequenceMax = 2 + GetDerLengthLength(integersMax) + integersMax;

                Assert.InRange(signature.Length, 8, sequenceMax);
                break;
            }

            default:
                throw new InvalidOperationException($"No handler for format {signatureFormat}");
            }
        }
Ejemplo n.º 17
0
        protected override bool TryCreateSignatureCore(
            ReadOnlySpan <byte> hash,
            Span <byte> destination,
            DSASignatureFormat signatureFormat,
            out int bytesWritten)
        {
            SafeDsaHandle key = GetKey();
            int           maxSignatureSize = Interop.Crypto.DsaEncodedSignatureSize(key);
            Span <byte>   signDestination  = stackalloc byte[SignatureStackBufSize];

            if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
            {
                int fieldSizeBytes     = Interop.Crypto.DsaSignatureFieldSize(key);
                int p1363SignatureSize = 2 * fieldSizeBytes;

                if (destination.Length < p1363SignatureSize)
                {
                    bytesWritten = 0;
                    return(false);
                }

                int fieldSizeBits = fieldSizeBytes * 8;

                ReadOnlySpan <byte> derSignature = SignHash(hash, signDestination, maxSignatureSize, key);
                bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, fieldSizeBits, destination);
                Debug.Assert(bytesWritten == p1363SignatureSize);
                return(true);
            }
            else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
            {
                if (destination.Length >= maxSignatureSize)
                {
                    signDestination = destination;
                }
                else if (maxSignatureSize > signDestination.Length)
                {
                    Debug.Fail($"Stack-based signDestination is insufficient ({maxSignatureSize} needed)");
                    bytesWritten = 0;
                    return(false);
                }

                ReadOnlySpan <byte> derSignature = SignHash(hash, signDestination, maxSignatureSize, key);

                if (destination == signDestination)
                {
                    bytesWritten = derSignature.Length;
                    return(true);
                }

                return(Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten));
            }
            else
            {
                Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
                throw new CryptographicException(
                          SR.Cryptography_UnknownSignatureFormat,
                          signatureFormat.ToString());
            }
        }
Ejemplo n.º 18
0
 protected override byte[] SignData(
     KeyDescription key,
     byte[] data,
     HashAlgorithmName hashAlgorithm,
     DSASignatureFormat signatureFormat)
 {
     return(((ECDsa)key.Key).SignData(data, hashAlgorithm, signatureFormat));
 }
Ejemplo n.º 19
0
 protected override bool VerifyHash(
     KeyDescription key,
     byte[] hash,
     byte[] signature,
     DSASignatureFormat signatureFormat)
 {
     return(((ECDsa)key.Key).VerifyHash(hash, signature, signatureFormat));
 }
Ejemplo n.º 20
0
 /// <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 ECDSA signature for the specified data.
 /// </returns>
 /// <exception cref="CryptographicException">
 ///   An error occurred in the hashing or signing operation.
 /// </exception>
 protected virtual byte[] SignDataCore(
     Stream data,
     HashAlgorithmName hashAlgorithm,
     DSASignatureFormat signatureFormat)
 {
     byte[] hash = HashData(data, hashAlgorithm);
     return(SignHashCore(hash, signatureFormat));
 }
Ejemplo n.º 21
0
        public void SignHashVerifyHash(DSASignatureFormat signatureFormat)
        {
            KeyDescription key = GetKey();

            byte[] hash      = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
            byte[] signature = SignHash(key, hash, signatureFormat);
            CheckLength(key, signature, signatureFormat);
            Assert.True(VerifyHash(key, hash, signature, signatureFormat));
        }
Ejemplo n.º 22
0
 /// <summary>
 ///   Verifies that a digital signature is valid for the provided data.
 /// </summary>
 /// <param name="data">The signed data.</param>
 /// <param name="signature">The signature to verify.</param>
 /// <param name="hashAlgorithm">The hash algorithm used to hash the data for the verification process.</param>
 /// <param name="signatureFormat">The encoding format for <paramref name="signature"/>.</param>
 /// <returns>
 ///   <see langword="true"/> if the digital signature is valid for the provided data; otherwise, <see langword="false"/>.
 /// </returns>
 /// <exception cref="CryptographicException">
 ///   An error occurred in the hashing or verification operation.
 /// </exception>
 protected virtual bool VerifyDataCore(
     Stream data,
     ReadOnlySpan <byte> signature,
     HashAlgorithmName hashAlgorithm,
     DSASignatureFormat signatureFormat)
 {
     byte[] hash = HashData(data, hashAlgorithm);
     return(VerifyHashCore(hash, signature, signatureFormat));
 }
Ejemplo n.º 23
0
        public void SignDataVerifyData_SHA1(DSASignatureFormat signatureFormat)
        {
            HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA1;

            KeyDescription key = GetKey();

            byte[] signature = SignData(key, _typeNameBytes, hashAlgorithm, signatureFormat);
            CheckLength(key, signature, signatureFormat);
            Assert.True(VerifyData(key, _typeNameBytes, signature, hashAlgorithm, signatureFormat));
        }
Ejemplo n.º 24
0
            protected override bool TrySignHashCore(
                ReadOnlySpan <byte> hash,
                Span <byte> destination,
                DSASignatureFormat signatureFormat,
                out int bytesWritten)
            {
                ThrowIfDisposed();
                SafeEcKeyHandle key = _key.Value;

                int         signatureLength = Interop.AndroidCrypto.EcDsaSize(key);
                Span <byte> signDestination = stackalloc byte[SignatureStackBufSize];

                if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
                {
                    int encodedSize = 2 * AsymmetricAlgorithmHelpers.BitsToBytes(KeySize);

                    if (destination.Length < encodedSize)
                    {
                        bytesWritten = 0;
                        return(false);
                    }

                    ReadOnlySpan <byte> derSignature = SignHash(hash, signDestination, signatureLength, key);
                    bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, KeySize, destination);
                    Debug.Assert(bytesWritten == encodedSize);
                    return(true);
                }
                else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
                {
                    if (destination.Length >= signatureLength)
                    {
                        signDestination = destination;
                    }
                    else if (signatureLength > signDestination.Length)
                    {
                        Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)");
                        bytesWritten = 0;
                        return(false);
                    }

                    ReadOnlySpan <byte> derSignature = SignHash(hash, signDestination, signatureLength, key);

                    if (destination == signDestination)
                    {
                        bytesWritten = derSignature.Length;
                        return(true);
                    }

                    return(Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten));
                }
                else
                {
                    throw new ArgumentOutOfRangeException(nameof(signatureFormat));
                }
            }
Ejemplo n.º 25
0
        /// <summary>
        ///   Verifies that a digital signature is valid for the provided data.
        /// </summary>
        /// <param name="data">The signed data.</param>
        /// <param name="signature">The signature to verify.</param>
        /// <param name="hashAlgorithm">The hash algorithm used to hash the data for the verification process.</param>
        /// <param name="signatureFormat">The encoding format for <paramref name="signature"/>.</param>
        /// <returns>
        ///   <see langword="true"/> if the digital signature is valid for the provided data; otherwise, <see langword="false"/>.
        /// </returns>
        /// <exception cref="CryptographicException">
        ///   An error occurred in the hashing or verification operation.
        /// </exception>
        protected virtual bool VerifyDataCore(
            ReadOnlySpan <byte> data,
            ReadOnlySpan <byte> signature,
            HashAlgorithmName hashAlgorithm,
            DSASignatureFormat signatureFormat)
        {
            Span <byte>         tmp  = stackalloc byte[HashBufferStackSize];
            ReadOnlySpan <byte> hash = HashSpanToTmp(data, hashAlgorithm, tmp);

            return(VerifySignatureCore(hash, signature, signatureFormat));
        }
Ejemplo n.º 26
0
        protected override bool VerifyHash(
            KeyDescription key,
            byte[] hash,
            byte[] signature,
            DSASignatureFormat signatureFormat)
        {
            ReadOnlySpan <byte> readOnlyHash      = hash;
            ReadOnlySpan <byte> readOnlySignature = signature;

            return(((ECDsa)key.Key).VerifyHash(readOnlyHash, readOnlySignature, signatureFormat));
        }
Ejemplo n.º 27
0
        /// <summary>
        ///   Computes the ECDSA signature for the specified hash value in the indicated format.
        /// </summary>
        /// <param name="hash">The hash value to sign.</param>
        /// <param name="signatureFormat">The encoding format to use for the signature.</param>
        /// <returns>
        ///   The ECDSA signature for the specified data.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///   <paramref name="hash"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="signatureFormat"/> is not a known format.
        /// </exception>
        /// <exception cref="CryptographicException">
        ///   An error occurred in the signing operation.
        /// </exception>
        public byte[] SignHash(byte[] hash, DSASignatureFormat signatureFormat)
        {
            ArgumentNullException.ThrowIfNull(hash);

            if (!signatureFormat.IsKnownValue())
            {
                throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat);
            }

            return(SignHashCore(hash, signatureFormat));
        }
Ejemplo n.º 28
0
        /// <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 ECDSA signature for the specified data.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        ///   <paramref name="data"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="signatureFormat"/> is not a known format.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="hashAlgorithm"/> has a <see langword="null"/> or empty <see cref="HashAlgorithmName.Name"/>.
        /// </exception>
        /// <exception cref="CryptographicException">
        ///   An error occurred in the hashing or signing operation.
        /// </exception>
        public byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, DSASignatureFormat signatureFormat)
        {
            ArgumentNullException.ThrowIfNull(data);
            ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
            if (!signatureFormat.IsKnownValue())
            {
                throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat);
            }

            return(SignDataCore(data, hashAlgorithm, signatureFormat));
        }
Ejemplo n.º 29
0
        /// <summary>
        ///   Verifies that a digital signature is valid for the provided hash.
        /// </summary>
        /// <param name="hash">The signed hash.</param>
        /// <param name="signature">The signature to verify.</param>
        /// <param name="signatureFormat">The encoding format for <paramref name="signature"/>.</param>
        /// <returns>
        ///   <see langword="true"/> if the digital signature is valid for the provided data; otherwise, <see langword="false"/>.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="signatureFormat"/> is not a known format.
        /// </exception>
        /// <exception cref="CryptographicException">
        ///   An error occurred in the verification operation.
        /// </exception>
        public bool VerifyHash(
            ReadOnlySpan <byte> hash,
            ReadOnlySpan <byte> signature,
            DSASignatureFormat signatureFormat)
        {
            if (!signatureFormat.IsKnownValue())
            {
                throw DSASignatureFormatHelpers.CreateUnknownValueException(signatureFormat);
            }

            return(VerifyHashCore(hash, signature, signatureFormat));
        }
Ejemplo n.º 30
0
        /// <summary>
        ///   Attempts to create the ECDSA signature for the specified data in the indicated format
        ///   into the provided buffer.
        /// </summary>
        /// <param name="data">The data to hash and sign.</param>
        /// <param name="destination">The buffer to receive the signature.</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>
        /// <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 TrySignDataCore(
            ReadOnlySpan <byte> data,
            Span <byte> destination,
            HashAlgorithmName hashAlgorithm,
            DSASignatureFormat signatureFormat,
            out int bytesWritten)
        {
            Span <byte>         hashTmp = stackalloc byte[HashBufferStackSize];
            ReadOnlySpan <byte> hash    = HashSpanToTmp(data, hashAlgorithm, hashTmp);

            return(TrySignHashCore(hash, destination, signatureFormat, out bytesWritten));
        }