diff options
author | Oren Novotny <oren@novotny.org> | 2018-09-30 08:49:27 -0400 |
---|---|---|
committer | Oren Novotny <oren@novotny.org> | 2018-09-30 08:49:27 -0400 |
commit | 22dcb7ce12fcd9142116aea0e36dffc3ce32b889 (patch) | |
tree | 4dd606ea73cd53f42d11f4f219575fb07ceb0f88 /crypto/src/asn1 | |
parent | fix filter (diff) | |
parent | RFC 8032: Avoid unnecessary doublings in precomputation (diff) | |
download | BouncyCastle.NET-ed25519-22dcb7ce12fcd9142116aea0e36dffc3ce32b889.tar.xz |
merge from master
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r-- | crypto/src/asn1/DerApplicationSpecific.cs | 33 | ||||
-rw-r--r-- | crypto/src/asn1/edec/EdECObjectIdentifiers.cs | 17 | ||||
-rw-r--r-- | crypto/src/asn1/pkcs/EncryptionScheme.cs | 8 | ||||
-rw-r--r-- | crypto/src/asn1/pkcs/PrivateKeyInfo.cs | 193 | ||||
-rw-r--r-- | crypto/src/asn1/x509/TBSCertificateStructure.cs | 8 |
5 files changed, 172 insertions, 87 deletions
diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs index 52467fabe..a2d57bf9d 100644 --- a/crypto/src/asn1/DerApplicationSpecific.cs +++ b/crypto/src/asn1/DerApplicationSpecific.cs @@ -199,38 +199,27 @@ namespace Org.BouncyCastle.Asn1 { int tagNo = input[0] & 0x1f; int index = 1; - // - // with tagged object tag number is bottom 5 bits, or stored at the start of the content - // + + // with tagged object tag number is bottom 5 bits, or stored at the start of the content if (tagNo == 0x1f) { - tagNo = 0; - - int b = input[index++] & 0xff; + int b = input[index++]; - // X.690-0207 8.1.2.4.2 + // X.690-0207 8.1.2.4.2 // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." if ((b & 0x7f) == 0) // Note: -1 will pass - { - throw new InvalidOperationException("corrupted stream - invalid high tag number found"); - } + throw new IOException("corrupted stream - invalid high tag number found"); - while ((b >= 0) && ((b & 0x80) != 0)) + while ((b & 0x80) != 0) { - tagNo |= (b & 0x7f); - tagNo <<= 7; - b = input[index++] & 0xff; + b = input[index++]; } - - tagNo |= (b & 0x7f); } - byte[] tmp = new byte[input.Length - index + 1]; - - Array.Copy(input, index, tmp, 1, tmp.Length - 1); - - tmp[0] = (byte)newTag; - + int remaining = input.Length - index; + byte[] tmp = new byte[1 + remaining]; + tmp[0] = (byte)newTag; + Array.Copy(input, index, tmp, 1, remaining); return tmp; } } diff --git a/crypto/src/asn1/edec/EdECObjectIdentifiers.cs b/crypto/src/asn1/edec/EdECObjectIdentifiers.cs new file mode 100644 index 000000000..f8c5713d8 --- /dev/null +++ b/crypto/src/asn1/edec/EdECObjectIdentifiers.cs @@ -0,0 +1,17 @@ +using System; + +namespace Org.BouncyCastle.Asn1.EdEC +{ + /** + * Edwards Elliptic Curve Object Identifiers (RFC 8410) + */ + public abstract class EdECObjectIdentifiers + { + public static readonly DerObjectIdentifier id_edwards_curve_algs = new DerObjectIdentifier("1.3.101"); + + public static readonly DerObjectIdentifier id_X25519 = id_edwards_curve_algs.Branch("110"); + public static readonly DerObjectIdentifier id_X448 = id_edwards_curve_algs.Branch("111"); + public static readonly DerObjectIdentifier id_Ed25519 = id_edwards_curve_algs.Branch("112"); + public static readonly DerObjectIdentifier id_Ed448 = id_edwards_curve_algs.Branch("113"); + } +} diff --git a/crypto/src/asn1/pkcs/EncryptionScheme.cs b/crypto/src/asn1/pkcs/EncryptionScheme.cs index 7b90ece53..34d26e172 100644 --- a/crypto/src/asn1/pkcs/EncryptionScheme.cs +++ b/crypto/src/asn1/pkcs/EncryptionScheme.cs @@ -8,7 +8,13 @@ namespace Org.BouncyCastle.Asn1.Pkcs public class EncryptionScheme : AlgorithmIdentifier { - public EncryptionScheme( + public EncryptionScheme( + DerObjectIdentifier objectID) + : base(objectID) + { + } + + public EncryptionScheme( DerObjectIdentifier objectID, Asn1Encodable parameters) : base(objectID, parameters) diff --git a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs index c5be7a315..dfb332fdd 100644 --- a/crypto/src/asn1/pkcs/PrivateKeyInfo.cs +++ b/crypto/src/asn1/pkcs/PrivateKeyInfo.cs @@ -4,15 +4,55 @@ using System.IO; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Math; +using Org.BouncyCastle.Utilities.Collections; namespace Org.BouncyCastle.Asn1.Pkcs { + /** + * RFC 5958 + * + * <pre> + * [IMPLICIT TAGS] + * + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] PublicKey OPTIONAL ]], + * ... + * } + * + * PrivateKeyInfo ::= OneAsymmetricKey + * + * Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) + * + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * { PUBLIC-KEY, + * { PrivateKeyAlgorithms } } + * + * PrivateKey ::= OCTET STRING + * -- Content varies based on type of key. The + * -- algorithm identifier dictates the format of + * -- the key. + * + * PublicKey ::= BIT STRING + * -- Content varies based on type of key. The + * -- algorithm identifier dictates the format of + * -- the key. + * + * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } + * </pre> + */ public class PrivateKeyInfo : Asn1Encodable { - private readonly Asn1OctetString privKey; - private readonly AlgorithmIdentifier algID; - private readonly Asn1Set attributes; + private readonly DerInteger version; + private readonly AlgorithmIdentifier privateKeyAlgorithm; + private readonly Asn1OctetString privateKey; + private readonly Asn1Set attributes; + private readonly DerBitString publicKey; public static PrivateKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly) { @@ -25,110 +65,139 @@ namespace Org.BouncyCastle.Asn1.Pkcs if (obj == null) return null; if (obj is PrivateKeyInfo) - return (PrivateKeyInfo) obj; + return (PrivateKeyInfo)obj; return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj)); } - public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Encodable privateKey) - : this(algID, privateKey, null) + private static int GetVersionValue(DerInteger version) + { + BigInteger bigValue = version.Value; + if (bigValue.CompareTo(BigInteger.Zero) < 0 || bigValue.CompareTo(BigInteger.One) > 0) + throw new ArgumentException("invalid version for private key info", "version"); + + return bigValue.IntValue; + } + + public PrivateKeyInfo( + AlgorithmIdentifier privateKeyAlgorithm, + Asn1Encodable privateKey) + : this(privateKeyAlgorithm, privateKey, null, null) { } public PrivateKeyInfo( - AlgorithmIdentifier algID, - Asn1Encodable privateKey, - Asn1Set attributes) + AlgorithmIdentifier privateKeyAlgorithm, + Asn1Encodable privateKey, + Asn1Set attributes) + : this(privateKeyAlgorithm, privateKey, attributes, null) { - this.algID = algID; - this.privKey = new DerOctetString(privateKey.GetEncoded(Asn1Encodable.Der)); + } + + public PrivateKeyInfo( + AlgorithmIdentifier privateKeyAlgorithm, + Asn1Encodable privateKey, + Asn1Set attributes, + byte[] publicKey) + { + this.version = new DerInteger(publicKey != null ? BigInteger.One : BigInteger.Zero); + this.privateKeyAlgorithm = privateKeyAlgorithm; + this.privateKey = new DerOctetString(privateKey); this.attributes = attributes; + this.publicKey = publicKey == null ? null : new DerBitString(publicKey); } private PrivateKeyInfo(Asn1Sequence seq) { IEnumerator e = seq.GetEnumerator(); - e.MoveNext(); - BigInteger version = ((DerInteger)e.Current).Value; - if (version.IntValue != 0) - { - throw new ArgumentException("wrong version for private key info: " + version.IntValue); - } + this.version = DerInteger.GetInstance(CollectionUtilities.RequireNext(e)); - e.MoveNext(); - algID = AlgorithmIdentifier.GetInstance(e.Current); - e.MoveNext(); - privKey = Asn1OctetString.GetInstance(e.Current); + int versionValue = GetVersionValue(version); - if (e.MoveNext()) + this.privateKeyAlgorithm = AlgorithmIdentifier.GetInstance(CollectionUtilities.RequireNext(e)); + this.privateKey = Asn1OctetString.GetInstance(CollectionUtilities.RequireNext(e)); + + int lastTag = -1; + while (e.MoveNext()) { - attributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current, false); + Asn1TaggedObject tagged = (Asn1TaggedObject)e.Current; + + int tag = tagged.TagNo; + if (tag <= lastTag) + throw new ArgumentException("invalid optional field in private key info", "seq"); + + lastTag = tag; + + switch (tag) + { + case 0: + { + this.attributes = Asn1Set.GetInstance(tagged, false); + break; + } + case 1: + { + if (versionValue < 1) + throw new ArgumentException("'publicKey' requires version v2(1) or later", "seq"); + + this.publicKey = DerBitString.GetInstance(tagged, false); + break; + } + default: + { + throw new ArgumentException("unknown optional field in private key info", "seq"); + } + } } } - public virtual AlgorithmIdentifier PrivateKeyAlgorithm + public virtual Asn1Set Attributes { - get { return algID; } + get { return attributes; } } - [Obsolete("Use 'PrivateKeyAlgorithm' property instead")] - public virtual AlgorithmIdentifier AlgorithmID + /// <summary>Return true if a public key is present, false otherwise.</summary> + public virtual bool HasPublicKey { - get { return algID; } + get { return publicKey != null; } + } + + public virtual AlgorithmIdentifier PrivateKeyAlgorithm + { + get { return privateKeyAlgorithm; } } public virtual Asn1Object ParsePrivateKey() { - return Asn1Object.FromByteArray(privKey.GetOctets()); + return Asn1Object.FromByteArray(privateKey.GetOctets()); } - [Obsolete("Use 'ParsePrivateKey' instead")] - public virtual Asn1Object PrivateKey + /// <summary>For when the public key is an ASN.1 encoding.</summary> + public virtual Asn1Object ParsePublicKey() { - get - { - try - { - return ParsePrivateKey(); - } - catch (IOException) - { - throw new InvalidOperationException("unable to parse private key"); - } - } + return publicKey == null ? null : Asn1Object.FromByteArray(publicKey.GetOctets()); } - public virtual Asn1Set Attributes + /// <summary>Return the public key as a raw bit string.</summary> + public virtual DerBitString PublicKeyData { - get { return attributes; } + get { return publicKey; } } - /** - * write out an RSA private key with its associated information - * as described in Pkcs8. - * <pre> - * PrivateKeyInfo ::= Sequence { - * version Version, - * privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}}, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL - * } - * Version ::= Integer {v1(0)} (v1,...) - * - * PrivateKey ::= OCTET STRING - * - * Attributes ::= Set OF Attr - * </pre> - */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(new DerInteger(0), algID, privKey); + Asn1EncodableVector v = new Asn1EncodableVector(version, privateKeyAlgorithm, privateKey); if (attributes != null) { v.Add(new DerTaggedObject(false, 0, attributes)); } + if (publicKey != null) + { + v.Add(new DerTaggedObject(false, 1, publicKey)); + } + return new DerSequence(v); } } diff --git a/crypto/src/asn1/x509/TBSCertificateStructure.cs b/crypto/src/asn1/x509/TBSCertificateStructure.cs index 9df078539..e69e985f5 100644 --- a/crypto/src/asn1/x509/TBSCertificateStructure.cs +++ b/crypto/src/asn1/x509/TBSCertificateStructure.cs @@ -121,7 +121,7 @@ namespace Org.BouncyCastle.Asn1.X509 while (extras > 0) { - DerTaggedObject extra = (DerTaggedObject) seq[seqStart + 6 + extras]; + DerTaggedObject extra = (DerTaggedObject)seq[seqStart + 6 + extras]; switch (extra.TagNo) { @@ -140,9 +140,13 @@ namespace Org.BouncyCastle.Asn1.X509 if (isV2) throw new ArgumentException("version 2 certificate cannot contain extensions"); - extensions = X509Extensions.GetInstance(extra); + extensions = X509Extensions.GetInstance(Asn1Sequence.GetInstance(extra, true)); break; } + default: + { + throw new ArgumentException("Unknown tag encountered in structure: " + extra.TagNo); + } } extras--; } |