| File: System\Security\Cryptography\X509Certificates\ECDsaX509SignatureGenerator.cs | Web Access |
| Project: src\runtime\src\libraries\System.Security.Cryptography\src\System.Security.Cryptography.csproj (System.Security.Cryptography) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Formats.Asn1; using Internal.Cryptography; namespace System.Security.Cryptography.X509Certificates { internal sealed class ECDsaX509SignatureGenerator : X509SignatureGenerator { private readonly ECDsa _key; internal ECDsaX509SignatureGenerator(ECDsa key) { Debug.Assert(key != null); _key = key; } public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlgorithm) { string oid; if (hashAlgorithm == HashAlgorithmName.SHA256) { oid = Oids.ECDsaWithSha256; } else if (hashAlgorithm == HashAlgorithmName.SHA384) { oid = Oids.ECDsaWithSha384; } else if (hashAlgorithm == HashAlgorithmName.SHA512) { oid = Oids.ECDsaWithSha512; } else if (hashAlgorithm == HashAlgorithmName.SHA3_256) { oid = Oids.ECDsaWithSha3_256; } else if (hashAlgorithm == HashAlgorithmName.SHA3_384) { oid = Oids.ECDsaWithSha3_384; } else if (hashAlgorithm == HashAlgorithmName.SHA3_512) { oid = Oids.ECDsaWithSha3_512; } else { throw new ArgumentOutOfRangeException( nameof(hashAlgorithm), hashAlgorithm, SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); } AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); writer.PushSequence(); writer.WriteObjectIdentifier(oid); writer.PopSequence(); return writer.Encode(); } public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) { return _key.SignData(data, hashAlgorithm, DSASignatureFormat.Rfc3279DerSequence); } protected override PublicKey BuildPublicKey() { ECParameters ecParameters = _key.ExportParameters(false); if (!ecParameters.Curve.IsNamed) { throw new InvalidOperationException(SR.Cryptography_ECC_NamedCurvesOnly); } string? curveOid = ecParameters.Curve.Oid.Value; byte[] curveOidEncoded; if (string.IsNullOrEmpty(curveOid)) { string friendlyName = ecParameters.Curve.Oid.FriendlyName!; // Translate the three curves that were supported Windows 7-8.1, but emit no Oid.Value; // otherwise just wash the friendly name back through Oid to see if we can get a value. curveOid = friendlyName switch { "nistP256" => Oids.secp256r1, "nistP384" => Oids.secp384r1, "nistP521" => Oids.secp521r1, _ => new Oid(friendlyName).Value, }; } AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); writer.WriteObjectIdentifier(curveOid!); curveOidEncoded = writer.Encode(); Debug.Assert(ecParameters.Q.X!.Length == ecParameters.Q.Y!.Length); byte[] uncompressedPoint = new byte[1 + ecParameters.Q.X.Length + ecParameters.Q.Y.Length]; // Uncompressed point (0x04) uncompressedPoint[0] = 0x04; Buffer.BlockCopy(ecParameters.Q.X, 0, uncompressedPoint, 1, ecParameters.Q.X.Length); Buffer.BlockCopy(ecParameters.Q.Y, 0, uncompressedPoint, 1 + ecParameters.Q.X.Length, ecParameters.Q.Y.Length); Oid ecPublicKey = Oids.EcPublicKeyOid; return new PublicKey( ecPublicKey, new AsnEncodedData(ecPublicKey, curveOidEncoded, skipCopy: true), new AsnEncodedData(ecPublicKey, uncompressedPoint, skipCopy: true)); } } }