internal ECParameters ExportParameters(bool includePrivateParameters, int keySizeInBIts) { SecKeyPair keys = GetOrGenerateKeys(keySizeInBIts); SafeSecKeyRefHandle keyHandle = includePrivateParameters ? keys.PrivateKey : keys.PublicKey; if (keyHandle == null) { throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); } DerSequenceReader keyReader = Interop.AppleCrypto.SecKeyExport(keyHandle, includePrivateParameters); ECParameters parameters = new ECParameters(); if (includePrivateParameters) { keyReader.ReadPkcs8Blob(ref parameters); } else { keyReader.ReadSubjectPublicKeyInfo(ref parameters); } int size = AsymmetricAlgorithmHelpers.BitsToBytes(keySizeInBIts); KeyBlobHelpers.PadOrTrim(ref parameters.Q.X, size); KeyBlobHelpers.PadOrTrim(ref parameters.Q.Y, size); if (includePrivateParameters) { KeyBlobHelpers.PadOrTrim(ref parameters.D, size); } return(parameters); }
/// <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)); } }
public override bool VerifyHash(byte[] hash, byte[] signature) { if (hash == null) { throw new ArgumentNullException(nameof(hash)); } if (signature == null) { throw new ArgumentNullException(nameof(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 CreateLiteSymmetricCipher( ReadOnlySpan <byte> key, ReadOnlySpan <byte> iv, bool encrypting, PaddingMode padding, CipherMode mode, int feedbackSizeInBits) { ValidateFeedbackSize(mode, feedbackSizeInBits); if (!iv.IsEmpty && iv.Length != AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize)) { throw new ArgumentException(SR.Cryptography_InvalidIVSize, nameof(iv)); } if (mode.UsesIv() && iv.IsEmpty) { throw new CryptographicException(SR.Cryptography_MissingIV); } byte[] processedKey = CopyAndValidateKey(key); int blockSizeInBytes = AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize); SafeAlgorithmHandle algorithmModeHandle = _outer.GetEphemeralModeHandle(mode, feedbackSizeInBits); return(new BasicSymmetricCipherLiteBCrypt( algorithmModeHandle, mode, blockSizeInBytes, _outer.GetPaddingSize(mode, feedbackSizeInBits), processedKey, ownsParentHandle: false, iv, encrypting)); }
public override bool TrySignHash(ReadOnlySpan <byte> hash, Span <byte> destination, out int bytesWritten) #endif { ThrowIfDisposed(); SafeEcKeyHandle key = _key.Value; int signatureLength = Interop.Crypto.EcDsaSize(key); Span <byte> signDestination = stackalloc byte[SignatureStackBufSize]; #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { #endif 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); #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } 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)); } #endif }
public override bool VerifyHash(ReadOnlySpan <byte> hash, ReadOnlySpan <byte> signature) #endif { ThrowIfDisposed(); Span <byte> derSignature = stackalloc byte[SignatureStackBufSize]; ReadOnlySpan <byte> toVerify = derSignature; #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) { #endif // 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); } if (AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer(signature, derSignature, out int derSize)) { toVerify = derSignature.Slice(0, derSize); } else { toVerify = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); } #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) { toVerify = signature; } else { Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); throw new CryptographicException( SR.Cryptography_UnknownSignatureFormat, signatureFormat.ToString()); } #endif SafeEcKeyHandle key = _key.Value; int verifyResult = Interop.Crypto.EcDsaVerify(hash, toVerify, key); return(verifyResult == 1); }
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)); }
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))); }
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)); }
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)); }
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))); }
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 void GenerateKey() { byte[] key = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BaseKeySize)); SetKey(key); }
public void GenerateIV() { byte[] iv = Helpers.GenerateRandom(AsymmetricAlgorithmHelpers.BitsToBytes(_outer.BlockSize)); _outer.IV = iv; }
/// <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); } } }