diff --git a/crypto/src/asn1/Asn1GeneralizedTime.cs b/crypto/src/asn1/Asn1GeneralizedTime.cs index affad50e25..64fe2c420b 100644 --- a/crypto/src/asn1/Asn1GeneralizedTime.cs +++ b/crypto/src/asn1/Asn1GeneralizedTime.cs @@ -48,6 +48,17 @@ public static Asn1GeneralizedTime GetInstance(object obj) throw new ArgumentException("failed to construct generalized time from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1GeneralizedTime)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct generalized time from byte[]: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), nameof(obj)); } diff --git a/crypto/src/asn1/Asn1Null.cs b/crypto/src/asn1/Asn1Null.cs index 77304c0fb1..638fa842fd 100644 --- a/crypto/src/asn1/Asn1Null.cs +++ b/crypto/src/asn1/Asn1Null.cs @@ -48,6 +48,17 @@ public static Asn1Null GetInstance(object obj) throw new ArgumentException("failed to construct NULL from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1Null)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct NULL from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs index a0e75c531d..d493c4c05b 100644 --- a/crypto/src/asn1/Asn1Object.cs +++ b/crypto/src/asn1/Asn1Object.cs @@ -48,28 +48,39 @@ public bool Equals(Asn1Object other) /// If there is a problem parsing the data, or parsing an object did not exhaust the available data. /// public static Asn1Object FromByteArray(byte[] data) - { + { + return FromByteArray(new ArraySegment(data)); + } + + /// Create a base ASN.1 object from a byte array. + /// The byte array to parse. + /// The base ASN.1 object represented by the byte array. + /// + /// If there is a problem parsing the data, or parsing an object did not exhaust the available data. + /// + public static Asn1Object FromByteArray(ArraySegment data) + { try - { - using (var asn1In = new Asn1InputStream(new MemoryStream(data, false), data.Length)) + { + using (var asn1In = new Asn1InputStream(new MemoryStream(data.Array ?? Array.Empty(), data.Offset, data.Count, false), data.Count)) { Asn1Object result = asn1In.ReadObject(); - if (data.Length != asn1In.Position) + if (data.Count != asn1In.Position) throw new IOException("extra data found after object"); return result; } - } - catch (InvalidCastException) - { - throw new IOException("cannot recognise object in byte array"); - } - } + } + catch (InvalidCastException) + { + throw new IOException("cannot recognise object in byte array"); + } + } - /// Read a base ASN.1 object from a stream. - /// The stream to parse. - /// The base ASN.1 object represented by the byte array. - /// If there is a problem parsing the data. - public static Asn1Object FromStream(Stream inStr) + /// Read a base ASN.1 object from a stream. + /// The stream to parse. + /// The base ASN.1 object represented by the byte array. + /// If there is a problem parsing the data. + public static Asn1Object FromStream(Stream inStr) { try { diff --git a/crypto/src/asn1/Asn1ObjectDescriptor.cs b/crypto/src/asn1/Asn1ObjectDescriptor.cs index 0d478a46dd..f811a34ce2 100644 --- a/crypto/src/asn1/Asn1ObjectDescriptor.cs +++ b/crypto/src/asn1/Asn1ObjectDescriptor.cs @@ -59,6 +59,17 @@ public static Asn1ObjectDescriptor GetInstance(object obj) throw new ArgumentException("failed to construct object descriptor from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1ObjectDescriptor)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct object descriptor from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/Asn1OctetString.cs b/crypto/src/asn1/Asn1OctetString.cs index d8a7bf27a7..4811099abe 100644 --- a/crypto/src/asn1/Asn1OctetString.cs +++ b/crypto/src/asn1/Asn1OctetString.cs @@ -59,6 +59,17 @@ public static Asn1OctetString GetInstance(object obj) throw new ArgumentException("failed to construct OCTET STRING from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1OctetString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct OCTET STRING from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/Asn1RelativeOid.cs b/crypto/src/asn1/Asn1RelativeOid.cs index b7df4b75a6..ed5c2cd5c7 100644 --- a/crypto/src/asn1/Asn1RelativeOid.cs +++ b/crypto/src/asn1/Asn1RelativeOid.cs @@ -52,6 +52,17 @@ public static Asn1RelativeOid GetInstance(object obj) throw new ArgumentException("failed to construct relative OID from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1RelativeOid)FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct relative OID from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/Asn1Sequence.cs b/crypto/src/asn1/Asn1Sequence.cs index 5b404d2483..a050c1a02d 100644 --- a/crypto/src/asn1/Asn1Sequence.cs +++ b/crypto/src/asn1/Asn1Sequence.cs @@ -53,6 +53,17 @@ public static Asn1Sequence GetInstance(object obj) throw new ArgumentException("failed to construct sequence from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1Sequence)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct sequence from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/Asn1Set.cs b/crypto/src/asn1/Asn1Set.cs index 0122971f67..710b970b3a 100644 --- a/crypto/src/asn1/Asn1Set.cs +++ b/crypto/src/asn1/Asn1Set.cs @@ -54,6 +54,17 @@ public static Asn1Set GetInstance(object obj) throw new ArgumentException("failed to construct set from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1Set)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct set from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), nameof(obj)); } diff --git a/crypto/src/asn1/Asn1TaggedObject.cs b/crypto/src/asn1/Asn1TaggedObject.cs index ea882f31d9..1354ca8777 100644 --- a/crypto/src/asn1/Asn1TaggedObject.cs +++ b/crypto/src/asn1/Asn1TaggedObject.cs @@ -44,6 +44,17 @@ public static Asn1TaggedObject GetInstance(object obj) throw new ArgumentException("failed to construct tagged object from byte[]", nameof(obj), e); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return CheckedCast(FromByteArray(arraySegment)); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct tagged object from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), nameof(obj)); } diff --git a/crypto/src/asn1/Asn1UniversalType.cs b/crypto/src/asn1/Asn1UniversalType.cs index 46cacb4362..c45116a1cc 100644 --- a/crypto/src/asn1/Asn1UniversalType.cs +++ b/crypto/src/asn1/Asn1UniversalType.cs @@ -40,6 +40,12 @@ internal Asn1Object FromByteArray(byte[] bytes) return CheckedCast(Asn1Object.FromByteArray(bytes)); } + /// + internal Asn1Object FromByteArray(ArraySegment bytes) + { + return CheckedCast(Asn1Object.FromByteArray(bytes)); + } + internal Asn1Object GetContextInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { if (Asn1Tags.ContextSpecific != taggedObject.TagClass) diff --git a/crypto/src/asn1/Asn1UtcTime.cs b/crypto/src/asn1/Asn1UtcTime.cs index bb9b6de8bd..8bc57e9da9 100644 --- a/crypto/src/asn1/Asn1UtcTime.cs +++ b/crypto/src/asn1/Asn1UtcTime.cs @@ -54,6 +54,17 @@ public static Asn1UtcTime GetInstance(object obj) throw new ArgumentException("failed to construct UTC time from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (Asn1UtcTime)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct UTC time from byte[]: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), nameof(obj)); } diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs index 7bf35d615a..b4006b293d 100644 --- a/crypto/src/asn1/DERExternal.cs +++ b/crypto/src/asn1/DERExternal.cs @@ -48,6 +48,17 @@ public static DerExternal GetInstance(object obj) throw new ArgumentException("failed to construct external from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerExternal)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct external from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs index 71a3f132ec..d45b7b75bc 100644 --- a/crypto/src/asn1/DerBMPString.cs +++ b/crypto/src/asn1/DerBMPString.cs @@ -57,6 +57,17 @@ public static DerBmpString GetInstance(object obj) throw new ArgumentException("failed to construct BMP string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerBmpString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct BMP string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs index bc3de7fe4b..c475fee19d 100644 --- a/crypto/src/asn1/DerBitString.cs +++ b/crypto/src/asn1/DerBitString.cs @@ -61,6 +61,17 @@ public static DerBitString GetInstance(object obj) throw new ArgumentException("failed to construct BIT STRING from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return GetInstance(FromByteArray(arraySegment)); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct BIT STRING from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerBoolean.cs b/crypto/src/asn1/DerBoolean.cs index 61a4dddb2d..1121c2d6d1 100644 --- a/crypto/src/asn1/DerBoolean.cs +++ b/crypto/src/asn1/DerBoolean.cs @@ -53,6 +53,17 @@ public static DerBoolean GetInstance(object obj) throw new ArgumentException("failed to construct boolean from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerBoolean)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct boolean from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs index f4725513e6..9bff14a2f4 100644 --- a/crypto/src/asn1/DerEnumerated.cs +++ b/crypto/src/asn1/DerEnumerated.cs @@ -51,6 +51,17 @@ public static DerEnumerated GetInstance(object obj) throw new ArgumentException("failed to construct enumerated from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerEnumerated)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct enumerated from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerGeneralString.cs b/crypto/src/asn1/DerGeneralString.cs index bfc6f6fd52..7b3378c56b 100644 --- a/crypto/src/asn1/DerGeneralString.cs +++ b/crypto/src/asn1/DerGeneralString.cs @@ -45,6 +45,17 @@ public static DerGeneralString GetInstance(object obj) throw new ArgumentException("failed to construct general string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerGeneralString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct general string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerGraphicString.cs b/crypto/src/asn1/DerGraphicString.cs index 7c3d1edb29..0283347190 100644 --- a/crypto/src/asn1/DerGraphicString.cs +++ b/crypto/src/asn1/DerGraphicString.cs @@ -52,6 +52,17 @@ public static DerGraphicString GetInstance(object obj) throw new ArgumentException("failed to construct graphic string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerGraphicString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct graphic string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/DerIA5String.cs b/crypto/src/asn1/DerIA5String.cs index 337cf2c2e6..00533e91d7 100644 --- a/crypto/src/asn1/DerIA5String.cs +++ b/crypto/src/asn1/DerIA5String.cs @@ -53,6 +53,17 @@ public static DerIA5String GetInstance(object obj) throw new ArgumentException("failed to construct IA5 string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerIA5String)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct IA5 string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs index 85585bea30..0cc0c20b45 100644 --- a/crypto/src/asn1/DerInteger.cs +++ b/crypto/src/asn1/DerInteger.cs @@ -65,6 +65,17 @@ public static DerInteger GetInstance(object obj) throw new ArgumentException("failed to construct integer from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerInteger)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct integer from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerNumericString.cs b/crypto/src/asn1/DerNumericString.cs index 2daca8b66f..b266f30720 100644 --- a/crypto/src/asn1/DerNumericString.cs +++ b/crypto/src/asn1/DerNumericString.cs @@ -53,6 +53,17 @@ public static DerNumericString GetInstance(object obj) throw new ArgumentException("failed to construct numeric string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerNumericString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct numeric string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs index 835f18d3d4..0098819de3 100644 --- a/crypto/src/asn1/DerObjectIdentifier.cs +++ b/crypto/src/asn1/DerObjectIdentifier.cs @@ -58,6 +58,17 @@ public static DerObjectIdentifier GetInstance(object obj) throw new ArgumentException("failed to construct object identifier from byte[]: " + e.Message); } } + else if (obj is ArraySegment) + { + try + { + return (DerObjectIdentifier)Meta.Instance.FromByteArray((ArraySegment)obj); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct object identifier from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/DerPrintableString.cs b/crypto/src/asn1/DerPrintableString.cs index 563e6fb586..7234c71371 100644 --- a/crypto/src/asn1/DerPrintableString.cs +++ b/crypto/src/asn1/DerPrintableString.cs @@ -53,6 +53,17 @@ public static DerPrintableString GetInstance(object obj) throw new ArgumentException("failed to construct printable string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerPrintableString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct printable string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerT61String.cs b/crypto/src/asn1/DerT61String.cs index 998a43bc23..cdbf5b01c8 100644 --- a/crypto/src/asn1/DerT61String.cs +++ b/crypto/src/asn1/DerT61String.cs @@ -53,6 +53,17 @@ public static DerT61String GetInstance(object obj) throw new ArgumentException("failed to construct T61 string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerT61String)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct T61 string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerUTF8String.cs b/crypto/src/asn1/DerUTF8String.cs index 9bee962e73..db60fd7955 100644 --- a/crypto/src/asn1/DerUTF8String.cs +++ b/crypto/src/asn1/DerUTF8String.cs @@ -53,6 +53,17 @@ public static DerUtf8String GetInstance(object obj) throw new ArgumentException("failed to construct UTF8 string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerUtf8String)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct UTF8 string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerUniversalString.cs b/crypto/src/asn1/DerUniversalString.cs index d65121ab0e..23f3b68467 100644 --- a/crypto/src/asn1/DerUniversalString.cs +++ b/crypto/src/asn1/DerUniversalString.cs @@ -57,6 +57,17 @@ public static DerUniversalString GetInstance(object obj) throw new ArgumentException("failed to construct universal string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerUniversalString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct universal string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/DerVideotexString.cs b/crypto/src/asn1/DerVideotexString.cs index 5019a66683..2b458d27f7 100644 --- a/crypto/src/asn1/DerVideotexString.cs +++ b/crypto/src/asn1/DerVideotexString.cs @@ -52,6 +52,17 @@ public static DerVideotexString GetInstance(object obj) throw new ArgumentException("failed to construct videotex string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerVideotexString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct videotex string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj"); } diff --git a/crypto/src/asn1/DerVisibleString.cs b/crypto/src/asn1/DerVisibleString.cs index 4c939988e5..78882551c6 100644 --- a/crypto/src/asn1/DerVisibleString.cs +++ b/crypto/src/asn1/DerVisibleString.cs @@ -53,6 +53,17 @@ public static DerVisibleString GetInstance(object obj) throw new ArgumentException("failed to construct visible string from byte[]: " + e.Message); } } + else if (obj is ArraySegment arraySegment) + { + try + { + return (DerVisibleString)Meta.Instance.FromByteArray(arraySegment); + } + catch (IOException e) + { + throw new ArgumentException("failed to construct visible string from ArraySegment: " + e.Message); + } + } throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } diff --git a/crypto/src/asn1/cmp/CmpCertificate.cs b/crypto/src/asn1/cmp/CmpCertificate.cs index e30eccca46..b732b30d9d 100644 --- a/crypto/src/asn1/cmp/CmpCertificate.cs +++ b/crypto/src/asn1/cmp/CmpCertificate.cs @@ -27,6 +27,10 @@ public static CmpCertificate GetInstance(object obj) { asn1Object = Asn1Object.FromByteArray(bytes); } + else if (obj is ArraySegment arraySegment) + { + asn1Object = Asn1Object.FromByteArray(arraySegment); + } if (asn1Object is Asn1TaggedObject asn1TaggedObject) return new CmpCertificate(asn1TaggedObject); diff --git a/crypto/src/asn1/x9/X962Parameters.cs b/crypto/src/asn1/x9/X962Parameters.cs index b863f4bfd8..0638b7ff94 100644 --- a/crypto/src/asn1/x9/X962Parameters.cs +++ b/crypto/src/asn1/x9/X962Parameters.cs @@ -17,16 +17,28 @@ public static X962Parameters GetInstance( return (X962Parameters)obj; } - if (obj is Asn1Object) + if (obj is Asn1Object asn1Object) { - return new X962Parameters((Asn1Object)obj); + return new X962Parameters(asn1Object); } - if (obj is byte[]) + if (obj is byte[] bytes) { try { - return new X962Parameters(Asn1Object.FromByteArray((byte[])obj)); + return new X962Parameters(Asn1Object.FromByteArray(bytes)); + } + catch (Exception e) + { + throw new ArgumentException("unable to parse encoded data: " + e.Message, e); + } + } + + if (obj is ArraySegment arraySegment) + { + try + { + return new X962Parameters(Asn1Object.FromByteArray(arraySegment)); } catch (Exception e) { diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs index c3e21f8ed9..c477adc7e6 100644 --- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs +++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs @@ -214,6 +214,12 @@ public Pkcs10CertificationRequest( { } + public Pkcs10CertificationRequest( + ArraySegment encoded) + : base((Asn1Sequence)Asn1Object.FromByteArray(encoded)) + { + } + public Pkcs10CertificationRequest( Asn1Sequence seq) : base(seq) diff --git a/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs b/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs index 447dbad277..c2bc6715dc 100644 --- a/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs @@ -101,7 +101,23 @@ public static HssPrivateKeyParameters GetInstance(object src) BinaryReader input = null; try // 1.5 / 1.6 compatibility { - input = new BinaryReader(new MemoryStream(bytes)); + input = new BinaryReader(new MemoryStream(bytes, false)); + return GetInstance(input); + } + finally + { + if (input != null) + { + input.Close(); + } + } + } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); return GetInstance(input); } finally @@ -428,7 +444,7 @@ private bool CompareLists(IList arr1, IList arr2) } return true; } - + public override byte[] GetEncoded() { diff --git a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs index 85b7812286..aa0cedc0c3 100644 --- a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs @@ -36,7 +36,20 @@ public static HssPublicKeyParameters GetInstance(object src) BinaryReader input = null; try // 1.5 / 1.6 compatibility { - input = new BinaryReader(new MemoryStream(bytes)); + input = new BinaryReader(new MemoryStream(bytes, false)); + return GetInstance(input); + } + finally + { + if (input != null) input.Close(); + } + } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); return GetInstance(input); } finally diff --git a/crypto/src/pqc/crypto/lms/HSSSignature.cs b/crypto/src/pqc/crypto/lms/HSSSignature.cs index 21f0397c8c..074b0b5a0f 100644 --- a/crypto/src/pqc/crypto/lms/HSSSignature.cs +++ b/crypto/src/pqc/crypto/lms/HSSSignature.cs @@ -57,7 +57,20 @@ public static HssSignature GetInstance(object src, int L) BinaryReader input = null; try // 1.5 / 1.6 compatibility { - input = new BinaryReader(new MemoryStream(bytes)); + input = new BinaryReader(new MemoryStream(bytes, false)); + return GetInstance(input, L); + } + finally + { + if (input != null) input.Close(); + } + } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); return GetInstance(input, L); } finally diff --git a/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs b/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs index ef3d4aced7..b9c24f7f66 100644 --- a/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs +++ b/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs @@ -56,6 +56,19 @@ public static LMOtsPublicKey GetInstance(object src) if (input != null) input.Close();//todo Platform Dispose } } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); + return GetInstance(input); + } + finally + { + if (input != null) input.Close();//todo Platform Dispose + } + } else if (src is MemoryStream memoryStream) { return GetInstance(Streams.ReadAll(memoryStream)); diff --git a/crypto/src/pqc/crypto/lms/LMOtsSignature.cs b/crypto/src/pqc/crypto/lms/LMOtsSignature.cs index c558666618..bdd8242b67 100644 --- a/crypto/src/pqc/crypto/lms/LMOtsSignature.cs +++ b/crypto/src/pqc/crypto/lms/LMOtsSignature.cs @@ -50,6 +50,19 @@ public static LMOtsSignature GetInstance(object src) if (input != null) input.Close(); } } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.4 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); + return GetInstance(input); + } + finally + { + if (input != null) input.Close(); + } + } else if (src is MemoryStream memoryStream) { return GetInstance(Streams.ReadAll(memoryStream)); diff --git a/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs b/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs index 278cbb04be..78300f0cd3 100644 --- a/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs @@ -136,6 +136,22 @@ public static LmsPrivateKeyParameters GetInstance(object src) } } } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); + return GetInstance(input); + } + finally + { + if (input != null) + { + input.Close(); + } + } + } else if (src is MemoryStream memoryStream) { return GetInstance(Streams.ReadAll(memoryStream)); diff --git a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs index e8c5d07e53..a7b3e8bb92 100644 --- a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs +++ b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs @@ -44,26 +44,42 @@ public static LmsPublicKeyParameters GetInstance(object src) return new LmsPublicKeyParameters(lmsParameter, ostTypeCode, T1, I); } else if (src is byte[] bytes) - { - BinaryReader input = null; - try // 1.5 / 1.6 compatibility - { - input = new BinaryReader(new MemoryStream(bytes, false)); - return GetInstance(input); - } - finally - { - if (input != null) - { - input.Close(); - } - } - } + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(bytes, false)); + return GetInstance(input); + } + finally + { + if (input != null) + { + input.Close(); + } + } + } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); + return GetInstance(input); + } + finally + { + if (input != null) + { + input.Close(); + } + } + } else if (src is MemoryStream memoryStream) { return GetInstance(Streams.ReadAll(memoryStream)); } - throw new Exception ($"cannot parse {src}"); + throw new Exception($"cannot parse {src}"); } public override byte[] GetEncoded() diff --git a/crypto/src/pqc/crypto/lms/LMSSignature.cs b/crypto/src/pqc/crypto/lms/LMSSignature.cs index a1ae475c18..96839897e8 100644 --- a/crypto/src/pqc/crypto/lms/LMSSignature.cs +++ b/crypto/src/pqc/crypto/lms/LMSSignature.cs @@ -59,6 +59,19 @@ public static LmsSignature GetInstance(object src) if (input != null) input.Close();// todo platform dispose } } + else if (src is ArraySegment arraySegment) + { + BinaryReader input = null; + try // 1.5 / 1.6 compatibility + { + input = new BinaryReader(new MemoryStream(arraySegment.Array ?? Array.Empty(), arraySegment.Offset, arraySegment.Count, false)); + return GetInstance(input); + } + finally + { + if (input != null) input.Close();// todo platform dispose + } + } else if (src is MemoryStream memoryStream) { return GetInstance(Streams.ReadAll(memoryStream)); diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs index d6fa87943f..37f8254df3 100644 --- a/crypto/src/security/PrivateKeyFactory.cs +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -31,6 +31,14 @@ public static AsymmetricKeyParameter CreateKey( Asn1Object.FromByteArray(privateKeyInfoData))); } + public static AsymmetricKeyParameter CreateKey( + ArraySegment privateKeyInfoData) + { + return CreateKey( + PrivateKeyInfo.GetInstance( + Asn1Object.FromByteArray(privateKeyInfoData))); + } + public static AsymmetricKeyParameter CreateKey( Stream inStr) { @@ -375,6 +383,13 @@ public static AsymmetricKeyParameter DecryptKey( return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData)); } + public static AsymmetricKeyParameter DecryptKey( + char[] passPhrase, + ArraySegment encryptedPrivateKeyInfoData) + { + return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData)); + } + public static AsymmetricKeyParameter DecryptKey( char[] passPhrase, Stream encryptedPrivateKeyInfoStream) diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs index d3ecef5c75..34dd0aeef8 100644 --- a/crypto/src/security/PublicKeyFactory.cs +++ b/crypto/src/security/PublicKeyFactory.cs @@ -30,6 +30,14 @@ public static AsymmetricKeyParameter CreateKey( Asn1Object.FromByteArray(keyInfoData))); } + public static AsymmetricKeyParameter CreateKey( + ArraySegment keyInfoData) + { + return CreateKey( + SubjectPublicKeyInfo.GetInstance( + Asn1Object.FromByteArray(keyInfoData))); + } + public static AsymmetricKeyParameter CreateKey( Stream inStr) { diff --git a/crypto/test/src/asn1/test/BitStringTest.cs b/crypto/test/src/asn1/test/BitStringTest.cs index 5e44aa40c7..b733d7c844 100644 --- a/crypto/test/src/asn1/test/BitStringTest.cs +++ b/crypto/test/src/asn1/test/BitStringTest.cs @@ -78,7 +78,37 @@ private void DoTestRandomPadBits() EncodingCheck(test, test3); EncodingCheck(test, test4); } + + private void DoTestRandomPadArraySegmentBits() + { + byte[] test = Hex.Decode("030206c0"); + + byte[] test1 = Hex.Decode("030206f0"); + byte[] test2 = Hex.Decode("030206c1"); + byte[] test3 = Hex.Decode("030206c7"); + byte[] test4 = Hex.Decode("030206d1"); + + EncodingCheck(MakeRandomArraySegment(test), MakeRandomArraySegment(test1)); + EncodingCheck(MakeRandomArraySegment(test), MakeRandomArraySegment(test2)); + EncodingCheck(MakeRandomArraySegment(test), MakeRandomArraySegment(test3)); + EncodingCheck(MakeRandomArraySegment(test), MakeRandomArraySegment(test4)); + } + + private static ArraySegment MakeRandomArraySegment(byte[] buffer) + { + var random = new Random(); + + var array = new byte[buffer.Length + random.Next(100)]; + + var offset = random.Next(array.Length - buffer.Length); + + random.NextBytes(array); + + buffer.CopyTo(array, offset); + return new ArraySegment(array, offset, buffer.Length); + } + private void EncodingCheck(byte[] derData, byte[] dlData) { if (Arrays.AreEqual(derData, Asn1Object.FromByteArray(dlData).GetEncoded())) @@ -104,6 +134,36 @@ private void EncodingCheck(byte[] derData, byte[] dlData) DerBitString der = DerBitString.GetInstance(derData); IsTrue("DER test failed", typeof(DerBitString) == der.GetType()); } + + private void EncodingCheck(ArraySegment derData, ArraySegment dlData) + { + var encodeed = Asn1Object.FromByteArray(dlData).GetEncoded(); + + if (Arrays.AreEqual(derData.Array, derData.Offset, derData.Offset + derData.Count, encodeed, 0, encodeed.Length)) + { + Fail("failed DL check"); + } + DerBitString dl = DerBitString.GetInstance(dlData); + + IsTrue("DL test failed", dl is DLBitString); + + encodeed = Asn1Object.FromByteArray(dlData).GetDerEncoded(); + if (!Arrays.AreEqual(derData.Array, derData.Offset, derData.Offset + derData.Count, encodeed, 0, encodeed.Length)) + { + Fail("failed DER check"); + } + try + { + // GetInstance should work for "an object that can be converted into [a DerBitString]". + DerBitString.GetInstance(dlData); + } + catch (ArgumentException) + { + Fail("failed DL encoding conversion"); + } + DerBitString der = DerBitString.GetInstance(derData); + IsTrue("DER test failed", typeof(DerBitString) == der.GetType()); + } public override void PerformTest() { @@ -148,6 +208,7 @@ public override void PerformTest() } DoTestRandomPadBits(); + DoTestRandomPadArraySegmentBits(); DoTestZeroLengthStrings(); }