Skip to content

Commit 6b98092

Browse files
authored
Use CopyWithPrivateKey (#1387)
* Use CopyWithPrivateKey * Fix test failure
1 parent 4eee36e commit 6b98092

File tree

1 file changed

+52
-24
lines changed

1 file changed

+52
-24
lines changed

Src/IronPython.Modules/_ssl.cs

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Linq;
1313
using System.Net.Security;
1414
using System.Net.Sockets;
15+
using System.Reflection;
1516
using System.Runtime.CompilerServices;
1617
using System.Security.Authentication;
1718
using System.Security.Cryptography;
@@ -190,7 +191,11 @@ public void load_verify_locations(CodeContext context, object cafile = null, str
190191
} else {
191192
throw PythonOps.TypeError("cafile should be a valid filesystem path");
192193
}
194+
#if NET5_0_OR_GREATER
195+
_cert_store.ImportFromPemFile(_cafile);
196+
#else
193197
_cert_store.Add(ReadCertificate(context, _cafile));
198+
#endif
194199
}
195200

196201
if (capath != null) {
@@ -631,8 +636,7 @@ public Bytes read(int size = -1) {
631636
if (length < span.Length) {
632637
buf = Bytes.Make(span.Slice(length).ToArray());
633638
span = span.Slice(0, length);
634-
}
635-
else {
639+
} else {
636640
buf = null;
637641
}
638642
span.CopyTo(resSpan);
@@ -903,7 +907,13 @@ private static PythonTuple IssuerFieldToPython(CodeContext context, string p) {
903907
return null;
904908
}
905909

906-
private static X509Certificate2 ReadCertificate(CodeContext context, string filename) {
910+
private static X509Certificate2 ReadCertificate(CodeContext context, string filename, bool readKey = false) {
911+
#if NET5_0_OR_GREATER
912+
if (readKey) {
913+
return X509Certificate2.CreateFromPemFile(filename);
914+
}
915+
#endif
916+
907917
string[] lines;
908918
try {
909919
lines = File.ReadAllLines(filename);
@@ -923,14 +933,17 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file
923933
} catch (Exception e) {
924934
throw ErrorDecoding(context, filename, e);
925935
}
936+
if (!readKey) return cert;
926937
} else if (lines[i] == "-----BEGIN RSA PRIVATE KEY-----") {
927938
var keyStr = ReadToEnd(lines, ref i, "-----END RSA PRIVATE KEY-----");
928939

929-
try {
930-
var keyBytes = Convert.FromBase64String(keyStr.ToString());
931-
key = ParsePkcs1DerEncodedPrivateKey(context, filename, keyBytes);
932-
} catch (Exception e) {
933-
throw ErrorDecoding(context, filename, e);
940+
if (readKey) {
941+
try {
942+
var keyBytes = Convert.FromBase64String(keyStr.ToString());
943+
key = ParsePkcs1DerEncodedPrivateKey(context, filename, keyBytes);
944+
} catch (Exception e) {
945+
throw ErrorDecoding(context, filename, e);
946+
}
934947
}
935948
}
936949
}
@@ -941,9 +954,7 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file
941954
if (cert != null) {
942955
if (key != null) {
943956
try {
944-
#pragma warning disable SYSLIB0028 // Type or member is obsolete
945-
cert.PrivateKey = key;
946-
#pragma warning restore SYSLIB0028 // Type or member is obsolete
957+
cert = cert.CopyWithPrivateKey(key);
947958
} catch (CryptographicException e) {
948959
throw ErrorDecoding(context, filename, "cert and private key are incompatible", e);
949960
}
@@ -954,6 +965,23 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file
954965
throw ErrorDecoding(context, filename, "certificate not found");
955966
}
956967

968+
#if !NETCOREAPP && !NET472_OR_GREATER
969+
#if NETSTANDARD
970+
private static MethodInfo CopyWithPrivateKeyMethodInfo = typeof(RSACertificateExtensions).GetMethod("CopyWithPrivateKey", new Type[] { typeof(X509Certificate2), typeof(System.Security.Cryptography.RSA) });
971+
#endif
972+
973+
private static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certificate, RSA privateKey) {
974+
#if NETSTANDARD
975+
if (CopyWithPrivateKeyMethodInfo is not null) {
976+
return (X509Certificate2)CopyWithPrivateKeyMethodInfo.Invoke(null, new object[] { certificate, privateKey });
977+
}
978+
#endif
979+
certificate.PrivateKey = privateKey;
980+
return certificate;
981+
}
982+
#endif
983+
984+
957985
#region Private Key Parsing
958986

959987
private const int ClassOffset = 6;
@@ -965,7 +993,7 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file
965993

966994
private const int NumberMask = 0x1f;
967995

968-
private const int UnivesalSequence = 0x10;
996+
private const int UniversalSequence = 0x10;
969997
private const int UniversalInteger = 0x02;
970998
private const int UniversalOctetString = 0x04;
971999

@@ -987,7 +1015,7 @@ private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeConte
9871015
// read header for sequence
9881016
if ((x[0] & ClassMask) != ClassUniversal) {
9891017
throw ErrorDecoding(context, filename, "failed to find universal class");
990-
} else if ((x[0] & NumberMask) != UnivesalSequence) {
1018+
} else if ((x[0] & NumberMask) != UniversalSequence) {
9911019
throw ErrorDecoding(context, filename, "failed to read sequence header");
9921020
}
9931021

@@ -996,7 +1024,7 @@ private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeConte
9961024
ReadLength(x, ref offset);
9971025

9981026
// read version
999-
int version = ReadUnivesalInt(x, ref offset);
1027+
int version = ReadUniversalInt(x, ref offset);
10001028
if (version != 0) {
10011029
// unsupported version
10021030
throw new InvalidOperationException(String.Format("bad vesion: {0}", version));
@@ -1006,20 +1034,20 @@ private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeConte
10061034
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
10071035
RSAParameters parameters = new RSAParameters();
10081036

1009-
parameters.Modulus = ReadUnivesalIntAsBytes(x, ref offset);
1010-
parameters.Exponent = ReadUnivesalIntAsBytes(x, ref offset);
1011-
parameters.D = ReadUnivesalIntAsBytes(x, ref offset);
1012-
parameters.P = ReadUnivesalIntAsBytes(x, ref offset);
1013-
parameters.Q = ReadUnivesalIntAsBytes(x, ref offset);
1014-
parameters.DP = ReadUnivesalIntAsBytes(x, ref offset);
1015-
parameters.DQ = ReadUnivesalIntAsBytes(x, ref offset);
1016-
parameters.InverseQ = ReadUnivesalIntAsBytes(x, ref offset);
1037+
parameters.Modulus = ReadUniversalIntAsBytes(x, ref offset);
1038+
parameters.Exponent = ReadUniversalIntAsBytes(x, ref offset);
1039+
parameters.D = ReadUniversalIntAsBytes(x, ref offset);
1040+
parameters.P = ReadUniversalIntAsBytes(x, ref offset);
1041+
parameters.Q = ReadUniversalIntAsBytes(x, ref offset);
1042+
parameters.DP = ReadUniversalIntAsBytes(x, ref offset);
1043+
parameters.DQ = ReadUniversalIntAsBytes(x, ref offset);
1044+
parameters.InverseQ = ReadUniversalIntAsBytes(x, ref offset);
10171045

10181046
provider.ImportParameters(parameters);
10191047
return provider;
10201048
}
10211049

1022-
private static byte[] ReadUnivesalIntAsBytes(byte[] x, ref int offset) {
1050+
private static byte[] ReadUniversalIntAsBytes(byte[] x, ref int offset) {
10231051
ReadIntType(x, ref offset);
10241052

10251053
int bytes = ReadLength(x, ref offset);
@@ -1046,7 +1074,7 @@ private static void ReadIntType(byte[] x, ref int offset) {
10461074
throw new InvalidOperationException(String.Format("expected version, fonud {0}", versionType));
10471075
}
10481076
}
1049-
private static int ReadUnivesalInt(byte[] x, ref int offset) {
1077+
private static int ReadUniversalInt(byte[] x, ref int offset) {
10501078
ReadIntType(x, ref offset);
10511079

10521080
return ReadInt(x, ref offset);

0 commit comments

Comments
 (0)