1212using System . Linq ;
1313using System . Net . Security ;
1414using System . Net . Sockets ;
15+ using System . Reflection ;
1516using System . Runtime . CompilerServices ;
1617using System . Security . Authentication ;
1718using 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