-
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: Import keys from RFC7468 PEM #31201
Comments
/cc @bartonjs |
It might make more sense to be error if
That way it doesn't hit future algorithm errors on upgrade. (It won't crack the PKCS#8, just the mere presence raises contention) Presumably there should be a sister method group for EncryptedPkcs8? And, nitpicky, you forgot ECDH :) |
I like your suggestion. For completeness, a BEGIN ENCRYPTED PRIVATE KEY will count as a BEGIN PRIVATE KEY.
Added.
Bah. Added. |
I was waffling on "BEGIN ENCRYPTED PRIVATE KEY" counting or not. I'm cool with being conservative and counting it (so an error for both "BEGIN ENCRYPTED PRIVATE KEY" and "BEGIN RSA PRIVATE KEY", but also an error for only "BEGIN ENCRYPTED PRIVATE KEY", unless that's supposed to try reading it with the null and empty passwords...) |
I hadn't planned on that. While that seems doable there is a lack of explicitness there that I personally don't care for. |
I concur. But that's why I was on the fence of whether or not it would count as making the input "ambiguous" :) |
namespace System.Security.Cryptography {
public partial class AsymmetricAlgorithm {
public virtual void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<char> password);
public virtual void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<byte> passwordBytes);
public virtual void ImportFromPem(ReadOnlySpan<char> input);
}
public partial class RSA : AsymmetricAlgorithm {
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<char> password);
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<byte> passwordBytes);
public override void ImportFromPem(ReadOnlySpan<char> input);
}
public partial class DSA : AsymmetricAlgorithm {
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<char> password);
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<byte> passwordBytes);
public override void ImportFromPem(ReadOnlySpan<char> input);
}
public partial class ECDsa : AsymmetricAlgorithm {
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<char> password);
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<byte> passwordBytes);
public override void ImportFromPem(ReadOnlySpan<char> input);
}
public partial class ECDiffieHellman : AsymmetricAlgorithm {
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<char> password);
public override void ImportFromEncryptedPem(ReadOnlySpan<char> input, ReadOnlySpan<byte> passwordBytes);
public override void ImportFromPem(ReadOnlySpan<char> input);
}
} |
I'm almost done with this and am working through the XML docs. I do have a question about it: since these methods will ultimately use other public and documented import methods as the workhorse, how do exceptions get documented? Is it expected that every exception |
I believe so, that's what I've been doing, at least.
Adding a Of course, you could decide to say |
Proposal:
The expected usage of this is to be able to import RFC 7468 textually encoded public and private keys with an API that "does the right thing". The intent of this API would be to allow importing keys that are encoded with a label indicating what kind of key it is.
Usage example:
Rationale:
There are a few different ways that a key can be encoded, when PEM encoded, such keys may look like "BEGIN PRIVATE KEY", "BEGIN RSA PRIVATE KEY", "BEGIN PUBLIC KEY", "BEGIN RSA PUBLIC KEY", etc. .NET Core 3 introduced APIs for importing these keys. However, this leaves developers the wrangle the key out of the file themselves, and know which API to use once they do. This is often not the experience with other software that when presented with a PEM textually encoded key, it often gets it right and just works.
Behaviors:
If the API can unambiguously determine the key that should be imported, it will import it, regardless of the rest of the contents such as a PEM aggregate. An example may be a PEM aggregate that contains a BEGIN CERTIFICATE and a BEGIN RSA PRIVATE KEY. In this circumstance, the BEGIN CERTIFICATE would be ignored because it is not a key.
If the contents contains multiple keys of the same algorithm, or a PKCS#8 key, an error is raised. This allows raising an error early without being forced to decode all PKCS#8 keys to determine what algorithm they are for.
For algorithms that support textually encoded parameters like DSA and ECDsa, if present, they will be imported as well and validated with the key. For example:
This private key is nistP256, as well as the EC parameters. Both explicit and named parameters should be supported. The parameters are not required, and appear at most once.
The PEM label and the key algorithm must match.
When
ImportFromEncryptedPem
is used, the PEM must be an encrypted private key. Even if contents contain exactly one key that could be imported because it is not encrypted, an error will still be raised.The implementation of this is dependent on something like #29588 being implemented first.
Considerations:
ReadOnlySpan<byte>
overloads, but that depends on encoding which complicates things, either by requiring one specific encoding (which?) or overloads to support all.The text was updated successfully, but these errors were encountered: