internal static AlgorithmIdentifier ToPresentationObject(this AlgorithmIdentifierAsn asn) { int keyLength; byte[] parameters = Array.Empty <byte>(); switch (asn.Algorithm.Value) { case Oids.Rc2Cbc: { if (asn.Parameters == null) { keyLength = 0; break; } Rc2CbcParameters rc2Params = Rc2CbcParameters.Decode( asn.Parameters.Value, AsnEncodingRules.BER); int keySize = rc2Params.GetEffectiveKeyBits(); // These are the only values .NET Framework would set. switch (keySize) { case 40: case 56: case 64: case 128: keyLength = keySize; break; default: keyLength = 0; break; } break; } case Oids.Rc4: { if (asn.Parameters == null) { keyLength = 0; break; } int saltLen = 0; AsnReader reader = new AsnReader(asn.Parameters.Value, AsnEncodingRules.BER); // DER NULL is considered the same as not present. // No call to ReadNull() is necessary because the serializer already verified that // there's no data after the [AnyValue] value. if (reader.PeekTag() != Asn1Tag.Null) { if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents)) { saltLen = contents.Length; } else { Span <byte> salt = stackalloc byte[KeyLengths.Rc4Max_128Bit / 8]; if (!reader.TryCopyOctetStringBytes(salt, out saltLen)) { throw new CryptographicException(); } } } keyLength = KeyLengths.Rc4Max_128Bit - 8 * saltLen; break; } case Oids.DesCbc: keyLength = KeyLengths.Des_64Bit; break; case Oids.TripleDesCbc: keyLength = KeyLengths.TripleDes_192Bit; break; case Oids.RsaOaep when !asn.HasNullEquivalentParameters(): keyLength = 0; parameters = asn.Parameters.Value.ToArray(); break; default: // .NET Framework doesn't set a keylength for AES, or any other algorithm than the ones // listed here. keyLength = 0; break; } return(new AlgorithmIdentifier(new Oid(asn.Algorithm), keyLength) { Parameters = parameters }); }
private static bool VerifyX509Signature( ReadOnlySpan <byte> toBeSigned, ReadOnlySpan <byte> signature, PublicKey publicKey, AlgorithmIdentifierAsn algorithmIdentifier) { RSA? rsa = publicKey.GetRSAPublicKey(); ECDsa?ecdsa = publicKey.GetECDsaPublicKey(); try { HashAlgorithmName hashAlg; if (algorithmIdentifier.Algorithm == Oids.RsaPss) { if (rsa is null || !algorithmIdentifier.Parameters.HasValue) { return(false); } PssParamsAsn pssParams = PssParamsAsn.Decode( algorithmIdentifier.Parameters.GetValueOrDefault(), AsnEncodingRules.DER); RSASignaturePadding padding = pssParams.GetSignaturePadding(); hashAlg = HashAlgorithmName.FromOid(pssParams.HashAlgorithm.Algorithm); return(rsa.VerifyData( toBeSigned, signature, hashAlg, padding)); } switch (algorithmIdentifier.Algorithm) { case Oids.RsaPkcs1Sha256: case Oids.ECDsaWithSha256: hashAlg = HashAlgorithmName.SHA256; break; case Oids.RsaPkcs1Sha384: case Oids.ECDsaWithSha384: hashAlg = HashAlgorithmName.SHA384; break; case Oids.RsaPkcs1Sha512: case Oids.ECDsaWithSha512: hashAlg = HashAlgorithmName.SHA512; break; case Oids.RsaPkcs1Sha1: case Oids.ECDsaWithSha1: hashAlg = HashAlgorithmName.SHA1; break; default: throw new NotSupportedException( SR.Format(SR.Cryptography_UnknownKeyAlgorithm, algorithmIdentifier.Algorithm)); } // All remaining supported algorithms have no defined parameters if (!algorithmIdentifier.HasNullEquivalentParameters()) { return(false); } switch (algorithmIdentifier.Algorithm) { case Oids.RsaPkcs1Sha256: case Oids.RsaPkcs1Sha384: case Oids.RsaPkcs1Sha512: case Oids.RsaPkcs1Sha1: if (rsa is null) { return(false); } return(rsa.VerifyData(toBeSigned, signature, hashAlg, RSASignaturePadding.Pkcs1)); case Oids.ECDsaWithSha256: case Oids.ECDsaWithSha384: case Oids.ECDsaWithSha512: case Oids.ECDsaWithSha1: if (ecdsa is null) { return(false); } return(ecdsa.VerifyData(toBeSigned, signature, hashAlg, DSASignatureFormat.Rfc3279DerSequence)); default: Debug.Fail( $"Algorithm ID {algorithmIdentifier.Algorithm} was in the first switch, but not the second"); return(false); } } catch (AsnContentException) { return(false); } catch (CryptographicException) { return(false); } finally { rsa?.Dispose(); ecdsa?.Dispose(); } }