-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Make System.Security.Cryptography.Oids constants public #87270
Comments
Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones Issue DetailsBackground and motivationAs a C# developer, I would like to have the Oids constants exposed to me so that I do not need to add my own constants for the same thing, thus reducing the size of my final output (every byte counts 😎) and reducing the chance of error. The runtime already includes many constants as an internal class, dotnet/runtime - Oids.cs which could easily be made public instead of internal. API Proposal// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace System.Security.Cryptography
{
public static partial class Oids
{
// Symmetric encryption algorithms
public const string Rc2Cbc = "1.2.840.113549.3.2";
public const string Rc4 = "1.2.840.113549.3.4";
public const string TripleDesCbc = "1.2.840.113549.3.7";
public const string DesCbc = "1.3.14.3.2.7";
public const string Aes128Cbc = "2.16.840.1.101.3.4.1.2";
public const string Aes192Cbc = "2.16.840.1.101.3.4.1.22";
public const string Aes256Cbc = "2.16.840.1.101.3.4.1.42";
// Asymmetric encryption algorithms
public const string Dsa = "1.2.840.10040.4.1";
public const string Rsa = "1.2.840.113549.1.1.1";
public const string RsaOaep = "1.2.840.113549.1.1.7";
public const string RsaPss = "1.2.840.113549.1.1.10";
public const string RsaPkcs1Md5 = "1.2.840.113549.1.1.4";
public const string RsaPkcs1Sha1 = "1.2.840.113549.1.1.5";
public const string RsaPkcs1Sha256 = "1.2.840.113549.1.1.11";
public const string RsaPkcs1Sha384 = "1.2.840.113549.1.1.12";
public const string RsaPkcs1Sha512 = "1.2.840.113549.1.1.13";
public const string RsaPkcs1Sha3_256 = "2.16.840.1.101.3.4.3.14";
public const string RsaPkcs1Sha3_384 = "2.16.840.1.101.3.4.3.15";
public const string RsaPkcs1Sha3_512 = "2.16.840.1.101.3.4.3.16";
public const string Esdh = "1.2.840.113549.1.9.16.3.5";
public const string EcDiffieHellman = "1.3.132.1.12";
public const string DiffieHellman = "1.2.840.10046.2.1";
public const string DiffieHellmanPkcs3 = "1.2.840.113549.1.3.1";
// Cryptographic Attribute Types
public const string SigningTime = "1.2.840.113549.1.9.5";
public const string ContentType = "1.2.840.113549.1.9.3";
public const string DocumentDescription = "1.3.6.1.4.1.311.88.2.2";
public const string MessageDigest = "1.2.840.113549.1.9.4";
public const string CounterSigner = "1.2.840.113549.1.9.6";
public const string SigningCertificate = "1.2.840.113549.1.9.16.2.12";
public const string SigningCertificateV2 = "1.2.840.113549.1.9.16.2.47";
public const string DocumentName = "1.3.6.1.4.1.311.88.2.1";
public const string LocalKeyId = "1.2.840.113549.1.9.21";
public const string EnrollCertTypeExtension = "1.3.6.1.4.1.311.20.2";
public const string UserPrincipalName = "1.3.6.1.4.1.311.20.2.3";
public const string CertificateTemplate = "1.3.6.1.4.1.311.21.7";
public const string ApplicationCertPolicies = "1.3.6.1.4.1.311.21.10";
public const string AuthorityInformationAccess = "1.3.6.1.5.5.7.1.1";
public const string OcspEndpoint = "1.3.6.1.5.5.7.48.1";
public const string CertificateAuthorityIssuers = "1.3.6.1.5.5.7.48.2";
public const string Pkcs9ExtensionRequest = "1.2.840.113549.1.9.14";
// Key wrap algorithms
public const string CmsRc2Wrap = "1.2.840.113549.1.9.16.3.7";
public const string Cms3DesWrap = "1.2.840.113549.1.9.16.3.6";
// PKCS7 Content Types.
public const string Pkcs7Data = "1.2.840.113549.1.7.1";
public const string Pkcs7Signed = "1.2.840.113549.1.7.2";
public const string Pkcs7Enveloped = "1.2.840.113549.1.7.3";
public const string Pkcs7SignedEnveloped = "1.2.840.113549.1.7.4";
public const string Pkcs7Hashed = "1.2.840.113549.1.7.5";
public const string Pkcs7Encrypted = "1.2.840.113549.1.7.6";
public const string Md5 = "1.2.840.113549.2.5";
public const string Sha1 = "1.3.14.3.2.26";
public const string Sha256 = "2.16.840.1.101.3.4.2.1";
public const string Sha384 = "2.16.840.1.101.3.4.2.2";
public const string Sha512 = "2.16.840.1.101.3.4.2.3";
public const string Sha3_256 = "2.16.840.1.101.3.4.2.8";
public const string Sha3_384 = "2.16.840.1.101.3.4.2.9";
public const string Sha3_512 = "2.16.840.1.101.3.4.2.10";
// DSA CMS uses the combined signature+digest OID
public const string DsaWithSha1 = "1.2.840.10040.4.3";
public const string DsaWithSha256 = "2.16.840.1.101.3.4.3.2";
public const string DsaWithSha384 = "2.16.840.1.101.3.4.3.3";
public const string DsaWithSha512 = "2.16.840.1.101.3.4.3.4";
// ECDSA CMS uses the combined signature+digest OID
// https://tools.ietf.org/html/rfc5753#section-2.1.1
public const string EcPrimeField = "1.2.840.10045.1.1";
public const string EcChar2Field = "1.2.840.10045.1.2";
public const string EcChar2TrinomialBasis = "1.2.840.10045.1.2.3.2";
public const string EcChar2PentanomialBasis = "1.2.840.10045.1.2.3.3";
public const string EcPublicKey = "1.2.840.10045.2.1";
public const string ECDsaWithSha1 = "1.2.840.10045.4.1";
public const string ECDsaWithSha256 = "1.2.840.10045.4.3.2";
public const string ECDsaWithSha384 = "1.2.840.10045.4.3.3";
public const string ECDsaWithSha512 = "1.2.840.10045.4.3.4";
public const string ECDsaWithSha3_256 = "2.16.840.1.101.3.4.3.10";
public const string ECDsaWithSha3_384 = "2.16.840.1.101.3.4.3.11";
public const string ECDsaWithSha3_512 = "2.16.840.1.101.3.4.3.12";
public const string Mgf1 = "1.2.840.113549.1.1.8";
public const string PSpecified = "1.2.840.113549.1.1.9";
// PKCS#7
public const string NoSignature = "1.3.6.1.5.5.7.6.2";
// X500 Names
public const string CommonName = "2.5.4.3";
public const string CountryOrRegionName = "2.5.4.6";
public const string LocalityName = "2.5.4.7";
public const string StateOrProvinceName = "2.5.4.8";
public const string Organization = "2.5.4.10";
public const string OrganizationalUnit = "2.5.4.11";
public const string EmailAddress = "1.2.840.113549.1.9.1";
// Cert Extensions
public const string BasicConstraints = "2.5.29.10";
public const string SubjectKeyIdentifier = "2.5.29.14";
public const string KeyUsage = "2.5.29.15";
public const string SubjectAltName = "2.5.29.17";
public const string IssuerAltName = "2.5.29.18";
public const string BasicConstraints2 = "2.5.29.19";
public const string CrlNumber = "2.5.29.20";
public const string CrlReasons = "2.5.29.21";
public const string CrlDistributionPoints = "2.5.29.31";
public const string CertPolicies = "2.5.29.32";
public const string AnyCertPolicy = "2.5.29.32.0";
public const string CertPolicyMappings = "2.5.29.33";
public const string AuthorityKeyIdentifier = "2.5.29.35";
public const string CertPolicyConstraints = "2.5.29.36";
public const string EnhancedKeyUsage = "2.5.29.37";
public const string InhibitAnyPolicyExtension = "2.5.29.54";
// RFC3161 Timestamping
public const string TstInfo = "1.2.840.113549.1.9.16.1.4";
public const string TimeStampingPurpose = "1.3.6.1.5.5.7.3.8";
// PKCS#12
private const string Pkcs12Prefix = "1.2.840.113549.1.12.";
private const string Pkcs12PbePrefix = Pkcs12Prefix + "1.";
public const string Pkcs12PbeWithShaAnd3Key3Des = Pkcs12PbePrefix + "3";
public const string Pkcs12PbeWithShaAnd2Key3Des = Pkcs12PbePrefix + "4";
public const string Pkcs12PbeWithShaAnd128BitRC2 = Pkcs12PbePrefix + "5";
public const string Pkcs12PbeWithShaAnd40BitRC2 = Pkcs12PbePrefix + "6";
private const string Pkcs12BagTypesPrefix = Pkcs12Prefix + "10.1.";
public const string Pkcs12KeyBag = Pkcs12BagTypesPrefix + "1";
public const string Pkcs12ShroudedKeyBag = Pkcs12BagTypesPrefix + "2";
public const string Pkcs12CertBag = Pkcs12BagTypesPrefix + "3";
public const string Pkcs12CrlBag = Pkcs12BagTypesPrefix + "4";
public const string Pkcs12SecretBag = Pkcs12BagTypesPrefix + "5";
public const string Pkcs12SafeContentsBag = Pkcs12BagTypesPrefix + "6";
public const string Pkcs12X509CertBagType = "1.2.840.113549.1.9.22.1";
public const string Pkcs12SdsiCertBagType = "1.2.840.113549.1.9.22.2";
// PKCS#5
private const string Pkcs5Prefix = "1.2.840.113549.1.5.";
public const string PbeWithMD5AndDESCBC = Pkcs5Prefix + "3";
public const string PbeWithMD5AndRC2CBC = Pkcs5Prefix + "6";
public const string PbeWithSha1AndDESCBC = Pkcs5Prefix + "10";
public const string PbeWithSha1AndRC2CBC = Pkcs5Prefix + "11";
public const string Pbkdf2 = Pkcs5Prefix + "12";
public const string PasswordBasedEncryptionScheme2 = Pkcs5Prefix + "13";
private const string RsaDsiDigestAlgorithmPrefix = "1.2.840.113549.2.";
public const string HmacWithSha1 = RsaDsiDigestAlgorithmPrefix + "7";
public const string HmacWithSha256 = RsaDsiDigestAlgorithmPrefix + "9";
public const string HmacWithSha384 = RsaDsiDigestAlgorithmPrefix + "10";
public const string HmacWithSha512 = RsaDsiDigestAlgorithmPrefix + "11";
// Elliptic Curve curve identifiers
public const string secp256r1 = "1.2.840.10045.3.1.7";
public const string secp384r1 = "1.3.132.0.34";
public const string secp521r1 = "1.3.132.0.35";
// LDAP
public const string DomainComponent = "0.9.2342.19200300.100.1.25";
}
} API Usage// Fancy the value
var c = new MyFancyCollection<int>();
c.Fancy(42);
// Getting the values out
foreach (var v in c)
Console.WriteLine(v); Alternative DesignsAn alternative design could include additional documentation, a big huge warning about their usage, or a tree hierarchy that maps the oids in oid hierarchy space. RisksThere are no risks of any backward compatibility issues. There is a slight business risk that some developers that ought not to do their own certificate processing will be empowered to do so with these constants available to them.
|
I've been thinking about this for a while and glad someone else proposed it 😄. My immediate thoughts are:
|
I'd agree strings are the way to go. Oid isn't heavy, but it's definitely not as light as a string. Calling .Value or adding an equality comparer could work as well. It's also less work since they are strings today. In my usage I'm doing
I don't mind a logical hierarchy like your example. Ultimately I initially was thinking what's easy to do, and Find internal > Replace public is almost no effort however there is some opportunity here to make it easier to use. I think you still need to know what you're doing to use these constants directly, and there is lots of public API today to make this work in many situations for the vast majority of use cases. |
While that may be a reasonable starting point, each and every name would have to be examined for appropriateness.
Two problems with this (though it might end up being the best answer anyways): 1) it's definitely arbitrary... id-rsaEncryption is one of the trickier ones to place... it can be a signature algorithm or an encryption algorithm, since it's just a generic "RSA will be used here, some other detail will provide better context". 2) nested types don't work equally well in all languages, so someone should see what the experience would be in C#, F#, VB.NET, and ideally even COBOL.NET. Yeah, we used nested types for well-known EC curves, but we also felt that the number of people using them would be small. While OID-users are still somewhat small, they're a bigger small than EC-curve specifiers/verifiers, so cross-language usability matters more.
Yep. The answer might be both... Another way for doing both would be to put strings as (e.g.) |
It will be great that WellKnown Oids became public. |
I looked around a bit at other ecosystems to see if, or how, anyone else did this. Java and Ruby use strings for OIDs. Go uses a typealias as Rust does. Rust has a very lean stdlib. All of their cryptography is in a separate crate, including OIDs. The RustCrypto project is as close as you could get to something in-box though. They generate a list of... every... OID. https://github.com/RustCrypto/formats/blob/master/const-oid/src/db/gen.rs "all of them" is probably too much for most people's needs. I was more interested in how they are organized. They are all in separate modules by the RFC or document that that defines them. Loosely, Rust modules could be static classes or namespaces. In .NET it would be something like: namespace System.Security.Cryptography.Oids;
public static class Fips202 {
public static Oid SHA3_256 => MakeOid("2.16.840.1.101.3.4.2.8");
// etc
}
public static class Rfc4519 {
public static Oid CommonName => MakeOid("2.5.4.3");
} There is a certain amount of this that I like, but some things going against it:
So I don't feel that rust gets us any close to a particular answer, but it does make me think a bit more strongly that any attempt to organize them is going to feel arbitrary. I don't feel that I am particularly closer to having a better understanding of the direction .NET should take, and there isn't a ton of prior art to look at. I think a point worth asking though, what OIDs do people feel that they are using frequently enough that would necessitate an accelerator? |
I think it's sufficient to start with EKUs, algos that are in common usage in .NET, and x509 related [for my use case 😀]. Ideally, I'd say you should be able to read an ASN1 stream for a bog standard cert from signtool and match the OIDs that would be present. Most of the current OIDs seem to work toward that purpose.
I've always thought a key feature for .NET and friends is our excellent tooling, IntelliSense in this case. This greatly aids most developers to be able to discover something IF they can get close to the member name, irrespective of the namespace it is under.
I guess because they'll be used in the box, we cannot have a separate NuGet package? |
If this API proposal is accepted, I'd like to also see |
Will this be made public in .NET9? |
Se la sont totalement priver, ça ne vous regarde pas je suis que sur ma page
et pas celle des autres devant la loi personne ne pourras m'empècher sais pas
a vous de me dire se que je doit faire et bon débarras avec vous mércie
…________________________________
De : Trevor Davis ***@***.***>
Envoyé : jeudi 30 mai 2024 17:42
À : dotnet/runtime ***@***.***>
Cc : Subscribed ***@***.***>
Objet : Re: [dotnet/runtime] [API Proposal]: Make System.Security.Cryptography.Oids constants public (Issue #87270)
Will this be made public in .NET9?
—
Reply to this email directly, view it on GitHub<#87270 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AUW2LQ7KUFHYZTIT7COOYC3ZE5CE7AVCNFSM6AAAAAAY7GGG3CVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMZZHE4TEOBTGM>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
This still has yet to be a complete API proposal and go through an API review. In particular, every name needs to be appropriate for public API.
|
Background and motivation
As a C# developer, I would like to have the Oids constants exposed to me so that I do not need to add my own constants for the same thing, thus reducing the size of my final output (every byte counts 😎) and reducing the chance of error.
The runtime already includes many constants as an internal class, dotnet/runtime - Oids.cs which could easily be made public instead of internal.
API Proposal
API Usage
Alternative Designs
An alternative design could include additional documentation, a big huge warning about their usage, or a tree hierarchy that maps the oids in oid hierarchy space.
Risks
There are no risks of any backward compatibility issues. There is a slight business risk that some developers that ought not to do their own certificate processing will be empowered to do so with these constants available to them.
The text was updated successfully, but these errors were encountered: