-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Support ECParameters that contain only D (Win, Linux). #33874
Conversation
c61eea8
to
56ff6ac
Compare
If D (private key) is supplied but not the public key (Q), permit this and allow the platform to re-calculate the public key from the private key.
If Q is missing for an ECParameters structure, import it as PKCS8 and let CNG construct Q appropriately.
The *Cng types currently do not support this; only the implementation-detail types do.
This comment has been minimized.
This comment has been minimized.
src/libraries/Common/src/System/Security/Cryptography/EccKeyFormatHelper.cs
Show resolved
Hide resolved
/cc @bartonjs |
|
||
try | ||
{ | ||
if (!writer.TryEncode(pkcs8Buffer, out int encodedWritten)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meta, for AsnWriter API purposes: I wonder if some sort of SendData<TState>(TState state, SpanAction<byte, TState> processor)
would be useful to avoid this ceremony without over-exposing the Span.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it turns out I didn't need any of this code anyway 😅.
I am curious why not make EncodeAsSpan
public?
Okay yes I see how it might be a bad idea. I suppose a public method that returns a span and marks it no longer writable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, were you thinking something like this?
public void SendData<TState>(TState state, SpanAction<T, byte> processor) {
// Validate
processor(state, _buffer.AsSpan(0, _offset));
}
Yeah that would be useful, I would think.
Is that still true with the change to use Q=(0,0) blobs instead of PKCS#8? |
For ECParameters, "(0,0)" works for explicit curves. However for PKCS8, it does not work. CNG does it's own PKCS8 handling it appears. That is, when using Unhandled exception. Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Unknown error (0xc0000005) at System.Security.Cryptography.CngKey.Import(ReadOnlySpan`1 keyBlob, String curveName, CngKeyBlobFormat format, CngProvider provider) at System.Security.Cryptography.CngPkcs8.ImportPkcs8(ReadOnlySpan`1 keyBlob) at System.Security.Cryptography.CngPkcs8.ImportPkcs8PrivateKey(ReadOnlySpan`1 source, Int32& bytesRead) at System.Security.Cryptography.ECDsaCng.ImportPkcs8PrivateKey(ReadOnlySpan`1 source, Int32& bytesRead) at Test.Program.Main(String[] args) in D:\code\personal\scratch\Program.cs:line 20 using ECDsaCng e = new ECDsaCng();
string keyStr = @"
MIIBMwIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB
AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA
///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV
AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg
9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A
AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBCcwJQIBAQQgO/HNs4GTcN1s
MVZ2GRwFlvPnq2YEUrzTEcSyUEr6axY=";
byte[] key = Convert.FromBase64String(keyStr);
e.ImportPkcs8PrivateKey(key, out _);
// generated with:
// openssl ecparam -genkey -name prime256v1 -noout | openssl ec -param_enc explicit -no_public | openssl pkey That leaves the following options.
|
Re: MacOS, I can look at that in about a week when a new Mac Mini gets delivered. Until then, my MacBook just can't muscle through this. |
I've reached out to my contacts to see if we can get that state changed. In the meantime... so that we don't have to try supporting key state parity with their PKCS#8 attribute parsing maybe it's
It's not pretty... but it works. |
Makes sense. I think that will keep me busy for a bit. 😄 |
@bartonjs how much review have you given this? Is it okay for me to rebase / squash this branch? |
Fully, I think.
If you need new stuff from master, merging would be preferred. (Sitting stale is fine) If you expect that it's going to be effectively a total rewrite from here, then I guess things that require a force-push are OK. |
No, I don't think that is the case. I'll stick with merge commits. I try not to let branches get too stale, at least hoping to be able to pick up some changes that fix test stability. |
Now that it is a real feature, we want to test all other explicit scenarios.
@bartonjs This will be *NO REVIEW* for a while. I'll ping when ready. |
This comment has been minimized.
This comment has been minimized.
@bartonjs I think this is ready for review again. To clarify something: the CNG PKCS8 importer doesn't like no PublicKey on the ECPrivateKey just for explicit curves. However, I incorrectly determined that it needed the correctly computed public key. Pushing 0,0 into the PKCS8 for the public key is enough to get CNG happy again, so we can avoid round-tripping through |
Thanks for jumping on this, @vcsjones. |
These changes allows importing EC keys for ECDsa and ECDiffieHellman where the private key (D) is specified but the public key (Q) is not.
This change is to remove a limitation on ECPrivateKey which, by definition, is not required to carry the public key, only the private key. It is expected that such keys are able to re-derive the public key from the private key. Prior to this change, the pre-computed public key was required.
MacOS does not currently support this. CNG and OpenSSL do.
Contributes to #33744