public static AsymmetricJwk Read(string key) { if (key is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } var data = key.AsSpan().Trim(); if (data.StartsWith(Pkcs8.PrivateKeyPrefix, StringComparison.Ordinal) && data.EndsWith(Pkcs8.PrivateKeySuffix, StringComparison.Ordinal)) { return(Pkcs8.ReadPrivateKey(data)); } else if (data.StartsWith(Pkcs8.PublicKeyPrefix, StringComparison.Ordinal) && data.EndsWith(Pkcs8.PublicKeySuffix, StringComparison.Ordinal)) { return(Pkcs8.ReadPublicKey(data)); } if (data.StartsWith(Pkcs1.PrivateRsaKeyPrefix, StringComparison.Ordinal) && data.EndsWith(Pkcs1.PrivatRsaKeySuffix, StringComparison.Ordinal)) { return(Pkcs1.ReadRsaPrivateKey(data)); } else if (data.StartsWith(Pkcs1.PublicRsaKeyPrefix, StringComparison.Ordinal) && data.EndsWith(Pkcs1.PublicRsaKeySuffix, StringComparison.Ordinal)) { return(Pkcs1.ReadRsaPublicKey(data)); } #if SUPPORT_ELLIPTIC_CURVE if (data.StartsWith(Pkcs1.PrivateECKeyPrefix, StringComparison.Ordinal) && data.EndsWith(Pkcs1.PrivateECKeySuffix, StringComparison.Ordinal)) { return(Pkcs1.ReadECPrivateKey(data)); } #endif throw new ArgumentException("PEM-encoded key be contained within valid prefix and suffix.", nameof(key)); }
// SEQUENCE // INTEGER 1 // OCTET STRING private key // [0] // OBJECT IDENTIFIER 1.2.840.10045.3.1.7 // [1] // BIT STRING public key public static ECJwk ReadECPrivateKey(string key) { string base64KeyData = key.Substring(PrivateECKeyPrefix.Length, key.Length - PrivateECKeyPrefix.Length - PrivateECKeySuffix.Length); byte[] keyData = Convert.FromBase64String(base64KeyData); var reader = new AsnReader(keyData); reader = reader.ReadSequence(); var version = reader.ReadInteger(); if (version.Length != 1 || version[0] != 1) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } var privateKey = reader.ReadOctetStringBytes().ToArray(); var readerOid = reader.ReadSequence(true); var curveOid = readerOid.ReadOid(); reader = reader.ReadSequence(true); var publicKey = reader.ReadBitStringBytes(); if (publicKey.IsEmpty) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } if (publicKey[0] != 0x04) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } if (publicKey.Length != 2 * privateKey.Length + 1) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } var x = publicKey.Slice(1, privateKey.Length).ToArray(); var y = publicKey.Slice(1 + privateKey.Length).ToArray(); if (reader.Read()) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } if (Pkcs8.IsP256(curveOid)) { return(ECJwk.FromByteArray(EllipticalCurve.P256, d: privateKey, x: x, y: y)); } else if (Pkcs8.IsP384(curveOid)) { return(ECJwk.FromByteArray(EllipticalCurve.P384, d: privateKey, x: x, y: y)); } else if (Pkcs8.IsP521(curveOid)) { return(ECJwk.FromByteArray(EllipticalCurve.P521, d: privateKey, x: x, y: y)); } else { throw new NotSupportedException(); } }
// SEQUENCE // INTEGER 1 // OCTET STRING private key // [0] // OBJECT IDENTIFIER 1.2.840.10045.3.1.7 // [1] // BIT STRING public key public static ECJwk ReadECPrivateKey(ReadOnlySpan <char> key) { var data = key.Slice(PrivateECKeyPrefix.Length, key.Length - PrivateECKeyPrefix.Length - PrivateECKeySuffix.Length); byte[] tmpArray; Span <byte> keyData = tmpArray = ArrayPool <byte> .Shared.Rent(Base64.GetArraySizeRequiredToDecode(data.Length)); try { int length = Base64.Decode(data, keyData); var reader = new AsnReader(keyData.Slice(0, length)); reader = reader.ReadSequence(); var version = reader.ReadInteger(); if (version.Length != 1 || version[0] != 1) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } var privateKey = reader.ReadOctetStringBytes().ToArray(); var readerOid = reader.ReadSequence(true); var curveOid = readerOid.ReadOid(); reader = reader.ReadSequence(true); var publicKey = reader.ReadBitStringBytes(); if (publicKey.IsEmpty) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } if (publicKey[0] != 0x04) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } if (publicKey.Length != 2 * privateKey.Length + 1) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } var x = publicKey.Slice(1, privateKey.Length).ToArray(); var y = publicKey.Slice(1 + privateKey.Length).ToArray(); if (reader.Read()) { ThrowHelper.ThrowInvalidOperationException_InvalidPem(); } if (Pkcs8.IsP256(curveOid)) { return(ECJwk.FromByteArray(EllipticalCurve.P256, d: privateKey, x: x, y: y)); } else if (Pkcs8.IsP384(curveOid)) { return(ECJwk.FromByteArray(EllipticalCurve.P384, d: privateKey, x: x, y: y)); } else if (Pkcs8.IsP521(curveOid)) { return(ECJwk.FromByteArray(EllipticalCurve.P521, d: privateKey, x: x, y: y)); } else { throw new NotSupportedException(); } } finally { ArrayPool <byte> .Shared.Return(tmpArray); } }