Example #1
0
        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));
        }
Example #2
0
        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));
        }
Example #3
0
        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));
        }
Example #4
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)
        {
            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);
            }
        }
Example #6
0
        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);
        }
Example #7
0
        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));
        }
Example #8
0
            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));
            }
Example #9
0
            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)));
            }
Example #10
0
        /// <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));
        }
Example #11
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 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));
        }
Example #13
0
        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);
            }
        }
Example #14
0
        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)));
        }
Example #16
0
        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);
            }
Example #18
0
            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);
            }
Example #19
0
        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));
        }
Example #20
0
        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
        }
Example #21
0
                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;
                }
Example #22
0
        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);
            }
        }
Example #23
0
        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);
            }
        }
Example #24
0
 protected override bool TryHashData(ReadOnlySpan <byte> data, Span <byte> destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
 AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten);
Example #25
0
 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));
Example #28
0
            /// <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);
                    }
                }
            }
Example #29
0
 public void GenerateIV()
 {
     byte[] iv = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize));
     _outer.IV = iv;
 }
Example #30
0
 public void GenerateKey()
 {
     byte[] key = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BaseKeySize));
     SetKey(key);
 }