Skip to content
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

Add support for OpenSSL PKCS#8 private key format #1496

Merged
merged 9 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,35 @@ The main types provided by this library are:
## Public Key Authentication

**SSH.NET** supports the following private key formats:
* RSA in OpenSSL PEM ("BEGIN RSA PRIVATE KEY") and ssh.com ("BEGIN SSH2 ENCRYPTED PRIVATE KEY") format
* DSA in OpenSSL PEM ("BEGIN DSA PRIVATE KEY") and ssh.com ("BEGIN SSH2 ENCRYPTED PRIVATE KEY") format
* ECDSA 256/384/521 in OpenSSL PEM format ("BEGIN EC PRIVATE KEY")
* ECDSA 256/384/521, ED25519 and RSA in OpenSSH key format ("BEGIN OPENSSH PRIVATE KEY")

Private keys in OpenSSL PEM and ssh.com format can be encrypted using one of the following cipher methods:
* RSA in
* OpenSSL traditional PEM format ("BEGIN RSA PRIVATE KEY")
* OpenSSL PKCS#8 PEM format ("BEGIN PRIVATE KEY", "BEGIN ENCRYPTED PRIVATE KEY")
* ssh.com format ("BEGIN SSH2 ENCRYPTED PRIVATE KEY")
* OpenSSH key format ("BEGIN OPENSSH PRIVATE KEY")
* DSA in
* OpenSSL traditional PEM format ("BEGIN DSA PRIVATE KEY")
* OpenSSL PKCS#8 PEM format ("BEGIN PRIVATE KEY", "BEGIN ENCRYPTED PRIVATE KEY")
* ssh.com format ("BEGIN SSH2 ENCRYPTED PRIVATE KEY")
* ECDSA 256/384/521 in
* OpenSSL traditional PEM format ("BEGIN EC PRIVATE KEY")
* OpenSSL PKCS#8 PEM format ("BEGIN PRIVATE KEY", "BEGIN ENCRYPTED PRIVATE KEY")
* OpenSSH key format ("BEGIN OPENSSH PRIVATE KEY")
* ED25519 in
* OpenSSH key format ("BEGIN OPENSSH PRIVATE KEY")

Private keys in OpenSSL traditional PEM format can be encrypted using one of the following cipher methods:
* DES-EDE3-CBC
* DES-EDE3-CFB
* DES-CBC
* AES-128-CBC
* AES-192-CBC
* AES-256-CBC

Private keys in OpenSSL PKCS#8 PEM format can be encrypted using any cipher method BouncyCastle supports.

Private keys in ssh.com format can be encrypted using one of the following cipher methods:
* 3des-cbc

Private keys in OpenSSH key format can be encrypted using one of the following cipher methods:
* 3des-cbc
* aes128-cbc
Expand Down
2 changes: 1 addition & 1 deletion src/Renci.SshNet/PrivateKeyConnectionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable
/// <param name="host">Connection host.</param>
/// <param name="username">Connection username.</param>
/// <param name="keyFiles">Connection key files.</param>
public PrivateKeyConnectionInfo(string host, string username, params PrivateKeyFile[] keyFiles)
public PrivateKeyConnectionInfo(string host, string username, params IPrivateKeySource[] keyFiles)
: this(host, DefaultPort, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty, keyFiles)
{
}
Expand Down
357 changes: 316 additions & 41 deletions src/Renci.SshNet/PrivateKeyFile.cs

Large diffs are not rendered by default.

37 changes: 11 additions & 26 deletions src/Renci.SshNet/Security/Cryptography/DsaKey.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#nullable enable
using System;
using System.Formats.Asn1;
using System.Numerics;
using System.Security.Cryptography;

Expand All @@ -16,6 +15,17 @@ public class DsaKey : Key, IDisposable
{
private DsaDigitalSignature? _digitalSignature;

/// <summary>
/// Gets the SSH name of the DSA Key.
/// </summary>
/// <returns>
/// The SSH name of the DSA Key.
/// </returns>
public override string ToString()
{
return "ssh-dss";
}

internal DSA DSA { get; }

/// <summary>
Expand Down Expand Up @@ -108,31 +118,6 @@ public DsaKey(SshKeyData publicKeyData)
DSA = LoadDSA();
}

/// <summary>
/// Initializes a new instance of the <see cref="DsaKey"/> class.
/// </summary>
/// <param name="privateKeyData">DER encoded private key data.</param>
public DsaKey(byte[] privateKeyData)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to remove this?

Same applies to the other key constructors

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remove it because there could be other DER data structures. The current Key constructors with byte array parameter assume the data is DER encoded OpenSSL traditional format which is not always true. It could be PKCS#8 format as well.

In practice, most package consumers are not necessarily call Key constructors directly. It might not bring huge impacts.

Anyway, to gracefully deprecate the constructors with byte array parameter, we can apply Obsolete attribute to the constructors and remove them in the future release. What do you think? @Rob-Hague

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sorry, I do not think there is a reason to break the existing contract.

I agree there is probably not many people using these constructors, and if we were starting from scratch we might do it differently. And although we make breaking changes practically every release, I think we can justify each of them. I do not believe this one can be justified.

As library developers, when we make a breaking change we are telling the user: "we expect you to bear the pain for our work". As a user, I can sometimes accept that when the user experience is improved and when it is easy to react to the change. Otherwise I find it annoying and frankly inconsiderate from the developers.

Whether we make this change or not, we experience no pain, so we should not cause any pain to users. We can instead improve things here by clarifying in the documentation that this constructor expects an OpenSSL format.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I didn't explain well.
The current Key constructors with byte array parameter assume the data is DER encoded OpenSSL traditional PKCS#1 format.
OpenSSL use PKCS#8 by default. It only uses PKCS#1 when option "-traditional" is specified.
The newer "genpkey" command even doesn't show "-traditional" option in the guide.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the situation, I just don't think it is worth deleting the constructor or changing its behaviour, unless you can somehow detect which format it is using while reading. If not, then the constructor should stay the same

Copy link
Collaborator Author

@scott-xu scott-xu Sep 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some more thinking, I'm leaning towards to just delete those constructors.

We removed old target frameworks. People who are using old frameworks should target to new frameworks. See #1109
We removed legacy algorithms. People who are using legacy algorithms should use new algorithms. See #1442

This change only affects people who are directly calling the constructor with PKCS#1 data. They should use PKCS#8 data instead.

Note: People who are using PrivateKeyFile are not affected. I believe most people are using PrivateKeyFile instead of each Key class.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This improvement does not require changing public API. It brings us zero benefits, and brings detriment to users

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If everyone agrees, then I can add them back. Would you mind sharing your thoughts here? @drieseng @WojciechNagorski @mus65

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree removing it is too much. But imho it should at least be obsoleted since it is ambigious and confusing (.NET 9 recently made a similiar API obsolete). But then there should be an alternative public API people can move to (I assume there is? I haven't checked the whole PR).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree removing it is too much. But imho it should at least be obsoleted since it is ambigious and confusing (.NET 9 recently made a similiar API obsolete). But then there should be an alternative public API people can move to (I assume there is? I haven't checked the whole PR).

Thanks for sharing the info. I know I'm not alone.

BTW, Microsoft calls their new design "one method, one purpose" which is exactly what I want to apply for method static string GetCurveOid(string curve_s).

{
if (privateKeyData is null)
{
throw new ArgumentNullException(nameof(privateKeyData));
}

var der = new AsnReader(privateKeyData, AsnEncodingRules.DER).ReadSequence();
_ = der.ReadInteger(); // skip version

P = der.ReadInteger();
Q = der.ReadInteger();
G = der.ReadInteger();
Y = der.ReadInteger();
X = der.ReadInteger();

der.ThrowIfNotEmpty();

DSA = LoadDSA();
}

/// <summary>
/// Initializes a new instance of the <see cref="DsaKey" /> class.
/// </summary>
Expand Down
27 changes: 2 additions & 25 deletions src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#nullable enable
using System;
using System.Diagnostics;
using System.Formats.Asn1;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
Expand Down Expand Up @@ -207,34 +206,12 @@ public EcdsaKey(SshKeyData publicKeyData)
/// <summary>
/// Initializes a new instance of the <see cref="EcdsaKey"/> class.
/// </summary>
/// <param name="curve">The curve name.</param>
/// <param name="curve">The curve oid.</param>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a nasty break. Let's try to avoid it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By reading the DER data, we get the curve oid string directly. It looks strange if we convert curve oid string to curve name in PrivateKeyFile and then convert name back to oid string in Ecdsakey.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's strange and unfortunate, but it's the publicly exposed contract, so my other comment applies here too. If you like, you can change it to accept either the name or oid

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to either document the breaking change in the release notes, or keep the current behavior but increase the code complexity (accept either name or oid). 😢

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be the latter. Does not seem that complex to me

diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs
index 70e2e1a9..6f275b20 100644
--- a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs
+++ b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs
@@ -271,17 +271,20 @@ private static Impl Import(string curve_oid, byte[] publickey, byte[]? privateke

         private static string GetCurveOid(string curve_s)
         {
-            if (string.Equals(curve_s, "nistp256", StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(curve_s, "nistp256", StringComparison.OrdinalIgnoreCase)
+                || curve_s == ECDSA_P256_OID_VALUE)
             {
                 return ECDSA_P256_OID_VALUE;
             }

-            if (string.Equals(curve_s, "nistp384", StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(curve_s, "nistp384", StringComparison.OrdinalIgnoreCase)
+                || curve_s == ECDSA_P384_OID_VALUE)
             {
                 return ECDSA_P384_OID_VALUE;
             }

-            if (string.Equals(curve_s, "nistp521", StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(curve_s, "nistp521", StringComparison.OrdinalIgnoreCase)
+                || curve_s == ECDSA_P521_OID_VALUE)
             {
                 return ECDSA_P521_OID_VALUE;
             }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure from coding perspective, it is not complex. It is just the method signature definition. Now the first parameter could be either name or oid. Would it break single responsibility principle?

/// <param name="publickey">Value of publickey.</param>
/// <param name="privatekey">Value of privatekey.</param>
public EcdsaKey(string curve, byte[] publickey, byte[] privatekey)
{
_impl = Import(GetCurveOid(curve), publickey, privatekey);
}

/// <summary>
/// Initializes a new instance of the <see cref="EcdsaKey"/> class.
/// </summary>
/// <param name="data">DER encoded private key data.</param>
public EcdsaKey(byte[] data)
{
var der = new AsnReader(data, AsnEncodingRules.DER).ReadSequence();
_ = der.ReadInteger(); // skip version

var privatekey = der.ReadOctetString().TrimLeadingZeros();

var s0 = der.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0, isConstructed: true));
var curve = s0.ReadObjectIdentifier();

var s1 = der.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1, isConstructed: true));
var pubkey = s1.ReadBitString(out _);

der.ThrowIfNotEmpty();

_impl = Import(curve, pubkey, privatekey);
_impl = Import(curve, publickey, privatekey.TrimLeadingZeros());
}

#pragma warning disable CA1859 // Use concrete types when possible for improved performance
Expand Down
38 changes: 17 additions & 21 deletions src/Renci.SshNet/Security/Cryptography/RsaKey.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#nullable enable
using System;
using System.Formats.Asn1;
using System.Numerics;
using System.Security.Cryptography;

Expand Down Expand Up @@ -159,27 +158,24 @@ public RsaKey(SshKeyData publicKeyData)
/// <summary>
/// Initializes a new instance of the <see cref="RsaKey"/> class.
/// </summary>
/// <param name="privateKeyData">DER encoded private key data.</param>
public RsaKey(byte[] privateKeyData)
/// <param name="modulus">The modulus.</param>
/// <param name="exponent">The exponent.</param>
/// <param name="d">The d.</param>
/// <param name="p">The p.</param>
/// <param name="q">The q.</param>
/// <param name="dp">The dp.</param>
/// <param name="dq">The dq.</param>
/// <param name="inverseQ">The inverse Q.</param>
public RsaKey(BigInteger modulus, BigInteger exponent, BigInteger d, BigInteger p, BigInteger q, BigInteger dp, BigInteger dq, BigInteger inverseQ)
{
if (privateKeyData is null)
{
throw new ArgumentNullException(nameof(privateKeyData));
}

var der = new AsnReader(privateKeyData, AsnEncodingRules.DER).ReadSequence();
_ = der.ReadInteger(); // skip version

Modulus = der.ReadInteger();
Exponent = der.ReadInteger();
D = der.ReadInteger();
P = der.ReadInteger();
Q = der.ReadInteger();
DP = der.ReadInteger();
DQ = der.ReadInteger();
InverseQ = der.ReadInteger();

der.ThrowIfNotEmpty();
Modulus = modulus;
Exponent = exponent;
D = d;
P = p;
Q = q;
DP = dp;
DQ = dq;
InverseQ = inverseQ;

RSA = RSA.Create();
RSA.ImportParameters(GetRSAParameters());
Expand Down
18 changes: 18 additions & 0 deletions test/Data/Key.PKCS8.DSA.Encrypted.Aes.256.CBC.12345.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICzTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIx8zJRpH4NWQCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCZ4Xbron+SzM6N2XBp7VaaBIIC
cMGjuaBslmf40+dbnXzyVm+i9sSvlJqpV5h03fOtBOYBZHWESNur8nw3J+taon/M
lTla0Mty70Cb+jMR+fehMmaGbVmkwSjrwi1ac4zIEZiFs0seEJUUmgDdh9Z0o6UG
VlUqMzmHJpHw4e+ywui7KOB2NNtz28C9Imgy+6ISMhsJfSYgo0pmI3L7n2Z6qm32
Ng0DES1oBdvSZkycV2Iy1ImbI6sJlWwd/WKGea6JBwo3n9UTHbzKcDoq+3Ze7JAb
Rok+UMf3gkoke1S0DmQFcpFbEy00yZUCcNrAYNcif4Ge/wQJ3sYBhXZbMhGhOjtK
jbBEcOzwdcF4iSvWRHyzzL3xsQ2M0s/Ss1OsALnTMfvtp6SYgXs8yvMZ907naxqQ
lWk0H8kKt6m/Gq4t12pl0HyaaFBi6gcvrxXmUFOIMZfa+p10cEwPHBXtEBqfr6dI
Kn/cJ7LV1cqHr2gogoruR23kLPFv8ANsaAdEty0VIfUDSc10dxxWYIYVzTDGilbE
dEHpMg5zYLyZyabwAt25YmlVeOtu80mBQI/HSQsNOifetbB0NuqDO+ZRj5Ka+6aY
ZazID+IuCLpOBCEEzEkA3G3t0Uc9gWZXh5M0VQAJmShmiE96JZLyoZLv/6XS3x00
m6wB/8y9eQ+/uIovmz+mqOmfyPkyK6gTmRyt1avdNbVQeqVPp0beStAhGHm0FvHN
qv7fkGrBWhK4GT5agrkwQeqrcksvZm1xOolIGHz7czMcU2Bkbbe1jc+bJAnZ691J
Bg5YOD/GVbPV2EuV9Bfo9DgFWu0WcXVR3xspIDVMyk0ZW2tl69ADQOZqsBetwnkP
/A==
-----END ENCRYPTED PRIVATE KEY-----
20 changes: 20 additions & 0 deletions test/Data/Key.PKCS8.DSA.pub
Rob-Hague marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN PUBLIC KEY-----
MIIDRzCCAjkGByqGSM44BAEwggIsAoIBAQC4ZsyBM8/72HeXKbEQP6jFPl8dmT+/
OtdMLHh28xZ4zn3YhIrAdkj0jbp9+neYfLV+6cbDyOlUUJNi3UXpHLQP6o2o3oVx
zCu+SXl/PmOpT5l6rKalcf32fyOyVkYahnUCWrjNvkB3VhmNLt6sGHMfU4JMc/ZK
nQrsZDnRvqP51QUOUX5ib+j7s04CPCaUc1eap+Wdvgf8RNvZlIC1wmPtbOhE7MMh
xp/ITBiTpBIYfzPWXCpi/vfybCzHReSgK+CyQ+Vl7kYG1oB6RsY/u4xFmP/Xns0R
WT61KaxznYcjBWEdDLQw0iqrFfikt5r1VSb58ofrwIY6W41X7Y68QOQDAiEAzKy8
LKPsvuFXLJtxISpkGdb05lMyuKzZYadz7u+dBw0CggEATVKeR1s+PuLUfVyoXXKn
jmPdHagz7+DGXGOtT4sFqMQ3QwBudNQYd4DrXmYf7/9bTaWZMJL76L+FJsbcQ7Kn
e+V5JsLpcoWz5iW6RAHPEf0GpvdgYrAz+5z0m/ImsX0ebUYTi/YyB/GL7LntvfOO
8U5E3EMhM6aoQQs5ZsxdV53PHx526r/+0Dbj+T7l5OczyEYscY34iXna0qwhKFQk
uCKWjmXEVTb+Ni0zco0/HVpaOL+1GtALzjil7662STmJ0eZR6MhGCaEzXc/DZy/v
WodE57gpX9QDXv5PT3xhWYAzgoVgq3F54umcBNRNuc7cAXTk8CEr4OW3HhlahJ8P
SgOCAQYAAoIBAQCMgluSOc42b3n4eYXPZXtSxzVUxmvnma3UQLlXB1dHSW0ZKGk5
YbQLorMgvP3DSPFgvfvISdrQvr7qjgE+Pf9nMwKmAMeKnnHs2+P7WWSH21ZA0Fcg
SPPhcyy5JluN0ReanTfXDRqU+OGX5uIO3I462C5F2KcJPuIL7l2hNG4eNO9Bfbjf
nHG537KSsrMTTLqlwd+bKpmmLZLV7LjeRQygtx6gEnnD8Nou4j2Mvw2ksZVxlT3g
A8w6ah/+ygL7S5rCzptKWtehhyhSQ2F46TuMX+8e0mcptnpsi2P1ON95UGcH1531
Nc9JCcTMqW5thCsNn1Ztku7k/AxtedMV8IiR
-----END PUBLIC KEY-----
15 changes: 15 additions & 0 deletions test/Data/Key.PKCS8.DSA.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN PRIVATE KEY-----
MIICZAIBADCCAjkGByqGSM44BAEwggIsAoIBAQC4ZsyBM8/72HeXKbEQP6jFPl8d
mT+/OtdMLHh28xZ4zn3YhIrAdkj0jbp9+neYfLV+6cbDyOlUUJNi3UXpHLQP6o2o
3oVxzCu+SXl/PmOpT5l6rKalcf32fyOyVkYahnUCWrjNvkB3VhmNLt6sGHMfU4JM
c/ZKnQrsZDnRvqP51QUOUX5ib+j7s04CPCaUc1eap+Wdvgf8RNvZlIC1wmPtbOhE
7MMhxp/ITBiTpBIYfzPWXCpi/vfybCzHReSgK+CyQ+Vl7kYG1oB6RsY/u4xFmP/X
ns0RWT61KaxznYcjBWEdDLQw0iqrFfikt5r1VSb58ofrwIY6W41X7Y68QOQDAiEA
zKy8LKPsvuFXLJtxISpkGdb05lMyuKzZYadz7u+dBw0CggEATVKeR1s+PuLUfVyo
XXKnjmPdHagz7+DGXGOtT4sFqMQ3QwBudNQYd4DrXmYf7/9bTaWZMJL76L+FJsbc
Q7Kne+V5JsLpcoWz5iW6RAHPEf0GpvdgYrAz+5z0m/ImsX0ebUYTi/YyB/GL7Lnt
vfOO8U5E3EMhM6aoQQs5ZsxdV53PHx526r/+0Dbj+T7l5OczyEYscY34iXna0qwh
KFQkuCKWjmXEVTb+Ni0zco0/HVpaOL+1GtALzjil7662STmJ0eZR6MhGCaEzXc/D
Zy/vWodE57gpX9QDXv5PT3xhWYAzgoVgq3F54umcBNRNuc7cAXTk8CEr4OW3Hhla
hJ8PSgQiAiBdup1WajP2Gjaw0DZcgmhyIJU5Vr/gpr2YamP4o7toGg==
-----END PRIVATE KEY-----
7 changes: 7 additions & 0 deletions test/Data/Key.PKCS8.ECDSA.Encrypted.Aes.256.CBC.12345.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjrR3XqO9Py4wICCAAw
DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEFwxueoXqeP7MFQLhPwl5lYEgZAp
rAlg8R/BEmtwr9FocvmRtw3SD3EQ5fJEJ2Jwtarca0owoLN9tFiVkEfJOaoMnZYI
OKFnRsV+Hs9QpkGsfo8y0hU3F1rtS6Ra0lrbZQZR5zrdFQC8RWSm0f4XjRATp9Fp
ZP5MokTvJYQXKNiFzMRV52K82Be/71B0Qn1E3FTSB+tV9KPffhkVf26U9H+VV5s=
-----END ENCRYPTED PRIVATE KEY-----
4 changes: 4 additions & 0 deletions test/Data/Key.PKCS8.ECDSA.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETyPeCi/ijYovYBoxbs2s7/8yPShy
94SMKf1noNO7c8hb3QeIU9bU5T46xloudiWb4aKWtKtVUzpd/nuE3RCYNA==
-----END PUBLIC KEY-----
5 changes: 5 additions & 0 deletions test/Data/Key.PKCS8.ECDSA.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghQBqtoVk/j7xffGP
HDJbLo+rti8YCRSUd3WCH2+/izKhRANCAARPI94KL+KNii9gGjFuzazv/zI9KHL3
hIwp/Weg07tzyFvdB4hT1tTlPjrGWi52JZvhopa0q1VTOl3+e4TdEJg0
-----END PRIVATE KEY-----
6 changes: 6 additions & 0 deletions test/Data/Key.PKCS8.ED25519.Encrypted.Aes.256.CBC.12345.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAj6QC1PblxAhgICCAAw
DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEECLlSAnzDE8JfUSJOvQKBlsEQEU4
sZQ9g5YV1pT0sVq63P13eTzCyFkSHm9MAAAYaZUjml9gEc0Y97mtRQyJitH8v/uO
GC1oQbbTG8xSSaXGUp8=
-----END ENCRYPTED PRIVATE KEY-----
3 changes: 3 additions & 0 deletions test/Data/Key.PKCS8.ED25519.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAFbHwYpK7u/6Xj8vjFjwV3Lz+8BX8nWV82eq8A2sYYXc=
-----END PUBLIC KEY-----
3 changes: 3 additions & 0 deletions test/Data/Key.PKCS8.ED25519.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIOf/LplXypaNcx42cZLGc2YsFlGjmNYvsavMHyOPa7HK
-----END PRIVATE KEY-----
30 changes: 30 additions & 0 deletions test/Data/Key.PKCS8.RSA.Encrypted.Aes.256.CBC.12345.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI/Zxlf/qHxdACAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBD5R1OO/2oOTK+1d4whXAgyBIIE
0ORLrx28RVHcjqRlgY1iRbvZNaTEDLkDiJrb3Qv2rBATw8UIWxf2B52cys4ogofL
LbWJI0hfRnAi8Fbt7tmi6Ap9n3ftAlVA6ITBeWVToXzRTrR5FHSMST9c3XwUEZ2L
5QEm3uM++fmxDXehrDKTmY/nWG9R12cKGqce5oOS1W5ObsgCnp40I4TmF5mFFcc1
RMex1gpgux3IYk2ysc6WGYZjlqFp0+yBdsEnS+jkJsVTA4/GSZbQY9BcGJA7fLta
/kHZ/+MDI3P5X/dMJUFZwHFk1lWmNeUE1TXqiwzeGo/+echgy1M0hK/gjlG7daJB
noCXTv6NPq6L3LGyTq+fOiGIxBFb8yimx16/osk3mQp/BgsTEuIRKgvAX2IkhYLF
CKPIYXUT7N/oo05S808Cid0kVdlKIPE/LQ3oYOJcB9mZ1e7EzqiwE3I26Cmm/Oon
6hexcTiVeRwnAdmpTiM2PMNEJdGUrfFgS2EGw3KgQhf2FimQE6bxJAh9mG7xppEb
l3FgwWHk42hCV8FtBSke9XLSpdu5VSiR0cj3wTnHP21dtkUjYQnfcNd9Wp0/CO7m
fY1WxsdrjZ2+yOtECaLNeF4qYjDJaak4/OHiS7VNGKEbuoma7NQajqYbozOyNIzS
ZZXC1YJCkudqVPd4+Kou2Cbvn6PZ100oo6Cyt6yf6K7CU+u960Tqg3TSW6gct7XX
EcRThVvPq+qqTI1hhYL+rYD/Sr2TgV5XkCG4zlF0TM53kJME9xTIvOlbDfTcrhqC
z8p6fCnbN7Irc01h2f9LYtoynlOtRKIQN077aJ8Hg9EdF2lYuTaReVf2Jwx/4Ir7
SaySo2mE3h543FjEMQghf6oUPFVNwPsnsTsS7mKgMvyI6VSZCx0+lGPyaUJI/No8
Zl5yk/N3wDUwIE44qYyW85wzIgwlUHVoTC/mpifJd4RUJ2FR2o76Cpsca03qltKB
+S4kVJOA4ijdB0zYo4FOyzaWSlzt9+/zS5kw+LYvTRFKcWxLC+VNOtfPmXiF8fZ4
TnhNdURMGJoxJ6WS26PhkRAgbom4tKJgbfmS+6cUyoinW+OCCVyU5uGBQQk/sL8M
YxqI3OfsfOlEaCXGjcc3OrRibVqm18cEadF04AC2kEa19RQU1STWs3lOLzBWNjsf
NNiKqiOqVee2QN3kflcSbK/IrAoZqqk3AWSNeof00QCrqkEt73ap0rY8UgYx5+9o
JinybftWyxk4MvJY/JWhjacSCMDQQfnDBSUEu1I0/8K6Y+HkzGNMEUVlCgYRyzGZ
jBEXQ/dKdGAa+2p4aI1dWeSJhJo7LC6vzAL18tUreFDwhxUk06hMjGsu0oXduIyL
GFv6DiM6KO4sVyRL54masPBPGEzOSaEqhQFlYf4R2LldR4wEYb6yGMlYXGPiXNfT
IB2vqkoTUyxeocKENPRt44rJ/eq2nOkaOqvh63pBUUSPn7rrDOdcFea9pVny9XaW
Ij6Qd1OOa3c00D/E+qojp4wXEiyLlyL1Y5yuL580ixQRF7xAKPenZ4sSjw/HqsG9
WILKpM9/jt1MYhEd+gKZOllMvyTJVV31EULoo/StubTBh9XF0hk9yEHgQ/ug+W8D
l05OpVnES4rr4Pnl/uEwOkrseWCgK0tm4LB7p+yWLCDp
-----END ENCRYPTED PRIVATE KEY-----
9 changes: 9 additions & 0 deletions test/Data/Key.PKCS8.RSA.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8xngYSu++gf77hpagAN
eVOju5c0vnTwpzN1IM+2O0DWw4OFosenjCsCTCIxmQxSqaZTwl/SeFB7AI7lTqIB
X1DT4loA8lUJFwJIymFCXqfsFe68cHDdYeDzcYuOaeny5RD1G9zAbeVjaNp/QvZT
wQjihAguP59AfCpcWHmvtMf7mqhfIvJQkuGvQufWwybbOL9sIvDpgY0ejhmimEVY
c7jIjga+hpWbPJUQb7xvzlySBfvV/wrh8arxvafzhhEl0bCmirwkatTp6NUnX6sa
S+cH/uxdtwbaXVpVqmnjan2eVQIoMrwb2JuUL6LcgjJfFR7wYWWkUPP87IiPTpqa
tQIDAQAB
-----END PUBLIC KEY-----
28 changes: 28 additions & 0 deletions test/Data/Key.PKCS8.RSA.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/zGeBhK776B/v
uGlqAA15U6O7lzS+dPCnM3Ugz7Y7QNbDg4Wix6eMKwJMIjGZDFKpplPCX9J4UHsA
juVOogFfUNPiWgDyVQkXAkjKYUJep+wV7rxwcN1h4PNxi45p6fLlEPUb3MBt5WNo
2n9C9lPBCOKECC4/n0B8KlxYea+0x/uaqF8i8lCS4a9C59bDJts4v2wi8OmBjR6O
GaKYRVhzuMiOBr6GlZs8lRBvvG/OXJIF+9X/CuHxqvG9p/OGESXRsKaKvCRq1Ono
1SdfqxpL5wf+7F23BtpdWlWqaeNqfZ5VAigyvBvYm5QvotyCMl8VHvBhZaRQ8/zs
iI9Ompq1AgMBAAECggEAAaQ9TuI6Fi1cgp0nMnv5duGfS+Elgit2434hAUIjMDrO
lmyh1Zdps3KAdJ2Go6WeRStHhGkfYHNojhlq/y3gnvZ5OHLRQcG2ZXREomN2jDVZ
465//eK1aQZMxxrCQgf5fHo/7Xhe9ux+RJI5gchLxgyZAGIf3+BcJAPqd5ZjtC4j
M/Iiuyq6hnqqELkJujIb9J9mIbokxrUdRuLnHqpY7dDs3ImjZDCDvDrnZw354Uf1
HDhNJtXOzJ6SiHGoYNiiQwqjjr5pHRZRMr2GmSK10wgZWlFiFtus4yfw50+grPcd
bCM3PQpff37hbES4RBgYhfLFMYzPyPqO0FmtbVKm8QKBgQDV+0AXXipHHiwBg+Rk
XQeiZuyh/O9olb3Cdv6Swe219aqefHV/UhhTj0F1q1WFCCvacntBxRFvFb80JL1v
07vNgEEBxpBSPljRl0gqPr4Dalv/WzuQuDOtfkURvDX2sMVusZLSAvIet0vy4zmB
eLXyF7V627XxL/laJQkpELEShQKBgQDldgZqsm4KC7CtEzWY25D8UUMjFo2KHfMK
swj0kxOz6beYpb52ZLhXbNXOlkkNkjKEJpP/EylFVCnknJgj2gjF9pUjDSIJGCsu
xRGbgBiUUUfrlQQsYthP0xrd9o5MEdyFU1m25tQzurcnrVScpx6ornlBCunZ8SrN
3+F5VZIWcQKBgQDNt7VQQelnYexwsHo8uuuCCG1q9p6772n1sSzhrqt4Cey0XXcg
pq5Ydxs5ozSeptJyOymge3NdVozx9nhhMDAXSzw0Fs/dIa+GIGjypEtNQU2c2/sS
EOUt4H1KpaVDu4Kz/ufmG4rmWNYddrJsdL6HNp/0s5HhhHu3XG/IGRIDeQKBgC/R
BYtMfYPYZcvbWertrmv2HzB7rakfjpsnLfGRiKSQSrMjruoLGSMWygNP7A9I7P/+
7g5UluAcptI+E7I86GEgfnmcbgBJKg6IAKBP9E9MFNmx5vm862jPDCU/EO4nNrYN
5X8o4QWanjpFc4Fljg0GtrvoI01IZWwbgGgBffzxAoGAManlzlx4Mqw1pr0hJTaH
Ro894B9uY3rdYnWGGm/HpqLuCBnshthTZw5ny6QjIX8FPT3Y811B5e8nAMV7OdCI
RdsW/jj0ELr6lRw1xnPjZp3OFGykHM+mYFO+yDFXBw/3eJXJgVqcA2lOIlD3lBvU
4+YTBzctcKHE1H/CVV1DYO4=
-----END PRIVATE KEY-----
Loading