diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs
index a0e8588b3..09e6b059d 100644
--- a/crypto/src/bcpg/SignaturePacket.cs
+++ b/crypto/src/bcpg/SignaturePacket.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.Utilities.IO;
@@ -24,8 +25,7 @@ namespace Org.BouncyCastle.Bcpg
private SignatureSubpacket[] unhashedData;
private byte[] signatureEncoding;
- internal SignaturePacket(
- BcpgInputStream bcpgIn)
+ internal SignaturePacket(BcpgInputStream bcpgIn)
{
version = bcpgIn.ReadByte();
@@ -125,42 +125,36 @@ namespace Org.BouncyCastle.Bcpg
switch (keyAlgorithm)
{
- case PublicKeyAlgorithmTag.RsaGeneral:
- case PublicKeyAlgorithmTag.RsaSign:
- MPInteger v = new MPInteger(bcpgIn);
- signature = new MPInteger[1]{ v };
- break;
- case PublicKeyAlgorithmTag.Dsa:
- MPInteger r = new MPInteger(bcpgIn);
- MPInteger s = new MPInteger(bcpgIn);
- signature = new MPInteger[2]{ r, s };
- break;
- case PublicKeyAlgorithmTag.ElGamalEncrypt: // yep, this really does happen sometimes.
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- MPInteger p = new MPInteger(bcpgIn);
- MPInteger g = new MPInteger(bcpgIn);
- MPInteger y = new MPInteger(bcpgIn);
- signature = new MPInteger[3]{ p, g, y };
- break;
- case PublicKeyAlgorithmTag.ECDsa:
- case PublicKeyAlgorithmTag.EdDsa:
- MPInteger ecR = new MPInteger(bcpgIn);
- MPInteger ecS = new MPInteger(bcpgIn);
- signature = new MPInteger[2]{ ecR, ecS };
- break;
- default:
- if (keyAlgorithm < PublicKeyAlgorithmTag.Experimental_1 || keyAlgorithm > PublicKeyAlgorithmTag.Experimental_11)
- throw new IOException("unknown signature key algorithm: " + keyAlgorithm);
-
- signature = null;
- MemoryStream bOut = new MemoryStream();
- int ch;
- while ((ch = bcpgIn.ReadByte()) >= 0)
- {
- bOut.WriteByte((byte) ch);
- }
- signatureEncoding = bOut.ToArray();
- break;
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ case PublicKeyAlgorithmTag.RsaSign:
+ MPInteger v = new MPInteger(bcpgIn);
+ signature = new MPInteger[1]{ v };
+ break;
+ case PublicKeyAlgorithmTag.Dsa:
+ MPInteger r = new MPInteger(bcpgIn);
+ MPInteger s = new MPInteger(bcpgIn);
+ signature = new MPInteger[2]{ r, s };
+ break;
+ case PublicKeyAlgorithmTag.ElGamalEncrypt: // yep, this really does happen sometimes.
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ MPInteger p = new MPInteger(bcpgIn);
+ MPInteger g = new MPInteger(bcpgIn);
+ MPInteger y = new MPInteger(bcpgIn);
+ signature = new MPInteger[3]{ p, g, y };
+ break;
+ case PublicKeyAlgorithmTag.ECDsa:
+ case PublicKeyAlgorithmTag.EdDsa:
+ MPInteger ecR = new MPInteger(bcpgIn);
+ MPInteger ecS = new MPInteger(bcpgIn);
+ signature = new MPInteger[2]{ ecR, ecS };
+ break;
+ default:
+ if (keyAlgorithm < PublicKeyAlgorithmTag.Experimental_1 || keyAlgorithm > PublicKeyAlgorithmTag.Experimental_11)
+ throw new IOException("unknown signature key algorithm: " + keyAlgorithm);
+
+ signature = null;
+ signatureEncoding = Streams.ReadAll(bcpgIn);
+ break;
}
}
@@ -238,23 +232,23 @@ namespace Org.BouncyCastle.Bcpg
}
}
- public int Version
- {
- get { return version; }
- }
+ public int Version => version;
- public int SignatureType
- {
- get { return signatureType; }
- }
+ public int SignatureType => signatureType;
- /**
+ /**
* return the keyId
* @return the keyId that created the signature.
*/
- public long KeyId
+ public long KeyId => keyId;
+
+ /**
+ * Return the signatures fingerprint.
+ * @return fingerprint (digest prefix) of the signature
+ */
+ public byte[] GetFingerprint()
{
- get { return keyId; }
+ return Arrays.Clone(fingerprint);
}
/**
@@ -314,24 +308,15 @@ namespace Org.BouncyCastle.Bcpg
return sOut.ToArray();
}
- public PublicKeyAlgorithmTag KeyAlgorithm
- {
- get { return keyAlgorithm; }
- }
+ public PublicKeyAlgorithmTag KeyAlgorithm => keyAlgorithm;
- public HashAlgorithmTag HashAlgorithm
- {
- get { return hashAlgorithm; }
- }
+ public HashAlgorithmTag HashAlgorithm => hashAlgorithm;
- /**
+ /**
* return the signature as a set of integers - note this is normalised to be the
* ASN.1 encoding of what appears in the signature packet.
*/
- public MPInteger[] GetSignature()
- {
- return signature;
- }
+ public MPInteger[] GetSignature() => signature;
/**
* Return the byte encoding of the signature section.
@@ -340,43 +325,34 @@ namespace Org.BouncyCastle.Bcpg
public byte[] GetSignatureBytes()
{
if (signatureEncoding != null)
- {
- return (byte[]) signatureEncoding.Clone();
- }
+ return (byte[])signatureEncoding.Clone();
MemoryStream bOut = new MemoryStream();
- BcpgOutputStream bcOut = new BcpgOutputStream(bOut);
- foreach (MPInteger sigObj in signature)
- {
- try
- {
- bcOut.WriteObject(sigObj);
- }
- catch (IOException e)
- {
- throw new Exception("internal error: " + e);
- }
- }
+ using (var pOut = new BcpgOutputStream(bOut))
+ {
+ foreach (MPInteger sigObj in signature)
+ {
+ try
+ {
+ pOut.WriteObject(sigObj);
+ }
+ catch (IOException e)
+ {
+ throw new Exception("internal error: " + e);
+ }
+ }
+ }
- return bOut.ToArray();
+ return bOut.ToArray();
}
- public SignatureSubpacket[] GetHashedSubPackets()
- {
- return hashedData;
- }
+ public SignatureSubpacket[] GetHashedSubPackets() => hashedData;
- public SignatureSubpacket[] GetUnhashedSubPackets()
- {
- return unhashedData;
- }
+ public SignatureSubpacket[] GetUnhashedSubPackets() => unhashedData;
/// <summary>Return the creation time in milliseconds since 1 Jan., 1970 UTC.</summary>
- public long CreationTime
- {
- get { return creationTime; }
- }
+ public long CreationTime => creationTime;
public override void Encode(BcpgOutputStream bcpgOut)
{
diff --git a/crypto/src/bcpg/SignatureSubpacket.cs b/crypto/src/bcpg/SignatureSubpacket.cs
index 5accadc14..c2186f373 100644
--- a/crypto/src/bcpg/SignatureSubpacket.cs
+++ b/crypto/src/bcpg/SignatureSubpacket.cs
@@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Bcpg
/// <summary>Return the generic data making up the packet.</summary>
public byte[] GetData()
{
- return (byte[]) data.Clone();
+ return (byte[])data.Clone();
}
public void Encode(
diff --git a/crypto/src/bcpg/SignatureSubpacketTags.cs b/crypto/src/bcpg/SignatureSubpacketTags.cs
index 1a8e254c0..0574c274b 100644
--- a/crypto/src/bcpg/SignatureSubpacketTags.cs
+++ b/crypto/src/bcpg/SignatureSubpacketTags.cs
@@ -25,9 +25,15 @@ namespace Org.BouncyCastle.Bcpg
PolicyUrl = 26, // policy URL
KeyFlags = 27, // key flags
SignerUserId = 28, // signer's user id
- RevocationReason = 29, // reason for revocation
- Features = 30, // features
- SignatureTarget = 31, // signature target
- EmbeddedSignature = 32 // embedded signature
- }
+ RevocationReason = 29, // reason for revocation
+ Features = 30, // features
+ SignatureTarget = 31, // signature target
+ EmbeddedSignature = 32, // embedded signature
+ IssuerFingerprint = 33, // issuer key fingerprint
+ //PreferredAeadAlgorithms = 34, // RESERVED since crypto-refresh-05
+ IntendedRecipientFingerprint = 35, // intended recipient fingerprint
+ AttestedCertifications = 37, // attested certifications (RESERVED)
+ KeyBlock = 38, // Key Block (RESERVED)
+ PreferredAeadAlgorithms = 39, // preferred AEAD algorithms
+ }
}
diff --git a/crypto/src/bcpg/SignatureSubpacketsReader.cs b/crypto/src/bcpg/SignatureSubpacketsReader.cs
index 86ad11207..35831fa9c 100644
--- a/crypto/src/bcpg/SignatureSubpacketsReader.cs
+++ b/crypto/src/bcpg/SignatureSubpacketsReader.cs
@@ -92,6 +92,8 @@ namespace Org.BouncyCastle.Bcpg
{
case SignatureSubpacketTag.CreationTime:
return new SignatureCreationTime(isCritical, isLongLength, data);
+ case SignatureSubpacketTag.EmbeddedSignature:
+ return new EmbeddedSignature(isCritical, isLongLength, data);
case SignatureSubpacketTag.KeyExpireTime:
return new KeyExpirationTime(isCritical, isLongLength, data);
case SignatureSubpacketTag.ExpireTime:
@@ -100,6 +102,8 @@ namespace Org.BouncyCastle.Bcpg
return new Revocable(isCritical, isLongLength, data);
case SignatureSubpacketTag.Exportable:
return new Exportable(isCritical, isLongLength, data);
+ case SignatureSubpacketTag.Features:
+ return new Features(isCritical, isLongLength, data);
case SignatureSubpacketTag.IssuerKeyId:
return new IssuerKeyId(isCritical, isLongLength, data);
case SignatureSubpacketTag.TrustSig:
@@ -107,19 +111,30 @@ namespace Org.BouncyCastle.Bcpg
case SignatureSubpacketTag.PreferredCompressionAlgorithms:
case SignatureSubpacketTag.PreferredHashAlgorithms:
case SignatureSubpacketTag.PreferredSymmetricAlgorithms:
+ case SignatureSubpacketTag.PreferredAeadAlgorithms:
return new PreferredAlgorithms(type, isCritical, isLongLength, data);
case SignatureSubpacketTag.KeyFlags:
return new KeyFlags(isCritical, isLongLength, data);
+ case SignatureSubpacketTag.PolicyUrl:
+ return new PolicyUrl(isCritical, isLongLength, data);
case SignatureSubpacketTag.PrimaryUserId:
return new PrimaryUserId(isCritical, isLongLength, data);
case SignatureSubpacketTag.SignerUserId:
return new SignerUserId(isCritical, isLongLength, data);
case SignatureSubpacketTag.NotationData:
return new NotationData(isCritical, isLongLength, data);
+ case SignatureSubpacketTag.RegExp:
+ return new RegularExpression(isCritical, isLongLength, data);
case SignatureSubpacketTag.RevocationReason:
return new RevocationReason(isCritical, isLongLength, data);
case SignatureSubpacketTag.RevocationKey:
return new RevocationKey(isCritical, isLongLength, data);
+ case SignatureSubpacketTag.SignatureTarget:
+ return new SignatureTarget(isCritical, isLongLength, data);
+ case SignatureSubpacketTag.IssuerFingerprint:
+ return new IssuerFingerprint(isCritical, isLongLength, data);
+ case SignatureSubpacketTag.IntendedRecipientFingerprint:
+ return new IntendedRecipientFingerprint(isCritical, isLongLength, data);
}
return new SignatureSubpacket(type, isCritical, isLongLength, data);
}
diff --git a/crypto/src/bcpg/sig/IntendedRecipientFingerprint.cs b/crypto/src/bcpg/sig/IntendedRecipientFingerprint.cs
new file mode 100644
index 000000000..7077c2d40
--- /dev/null
+++ b/crypto/src/bcpg/sig/IntendedRecipientFingerprint.cs
@@ -0,0 +1,28 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * packet giving the intended recipient fingerprint.
+ */
+ public class IntendedRecipientFingerprint
+ : SignatureSubpacket
+ {
+ public IntendedRecipientFingerprint(bool critical, bool isLongLength, byte[] data)
+ : base(SignatureSubpacketTag.IntendedRecipientFingerprint, critical, isLongLength, data)
+ {
+ }
+
+ public IntendedRecipientFingerprint(bool critical, int keyVersion, byte[] fingerprint)
+ : base(SignatureSubpacketTag.IntendedRecipientFingerprint, critical, false,
+ Arrays.Prepend(fingerprint, (byte)keyVersion))
+ {
+ }
+
+ public int KeyVersion => data[0];
+
+ public byte[] GetFingerprint() => Arrays.CopyOfRange(data, 1, data.Length);
+ }
+}
diff --git a/crypto/src/bcpg/sig/IssuerFingerprint.cs b/crypto/src/bcpg/sig/IssuerFingerprint.cs
new file mode 100644
index 000000000..469a8e0d8
--- /dev/null
+++ b/crypto/src/bcpg/sig/IssuerFingerprint.cs
@@ -0,0 +1,28 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * packet giving the issuer key fingerprint.
+ */
+ public class IssuerFingerprint
+ : SignatureSubpacket
+ {
+ public IssuerFingerprint(bool critical, bool isLongLength, byte[] data)
+ : base(SignatureSubpacketTag.IssuerFingerprint, critical, isLongLength, data)
+ {
+ }
+
+ public IssuerFingerprint(bool critical, int keyVersion, byte[] fingerprint)
+ : base(SignatureSubpacketTag.IssuerFingerprint, critical, false,
+ Arrays.Prepend(fingerprint, (byte)keyVersion))
+ {
+ }
+
+ public int KeyVersion => data[0];
+
+ public byte[] GetFingerprint() => Arrays.CopyOfRange(data, 1, data.Length);
+ }
+}
diff --git a/crypto/src/bcpg/sig/PolicyUrl.cs b/crypto/src/bcpg/sig/PolicyUrl.cs
new file mode 100644
index 000000000..16f4d1a64
--- /dev/null
+++ b/crypto/src/bcpg/sig/PolicyUrl.cs
@@ -0,0 +1,24 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ public class PolicyUrl
+ : SignatureSubpacket
+ {
+ public PolicyUrl(bool critical, string url)
+ : this(critical, false, Strings.ToUtf8ByteArray(url))
+ {
+ }
+
+ public PolicyUrl(bool critical, bool isLongLength, byte[] data)
+ : base(SignatureSubpacketTag.PolicyUrl, critical, isLongLength, data)
+ {
+ }
+
+ public string Url => Strings.FromUtf8ByteArray(data);
+
+ public byte[] GetRawUrl() => Arrays.Clone(data);
+ }
+}
diff --git a/crypto/src/bcpg/sig/RegularExpression.cs b/crypto/src/bcpg/sig/RegularExpression.cs
new file mode 100644
index 000000000..c4b48ea2a
--- /dev/null
+++ b/crypto/src/bcpg/sig/RegularExpression.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Text.RegularExpressions;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * Regexp Packet - RFC 4880 5.2.3.14. Note: the RFC says the byte encoding is to be null terminated.
+ */
+ public class RegularExpression
+ : SignatureSubpacket
+ {
+ public RegularExpression(bool critical, bool isLongLength, byte[] data)
+ : base(SignatureSubpacketTag.RegExp, critical, isLongLength, data)
+ {
+ if (data[data.Length - 1] != 0)
+ throw new ArgumentException("data in regex missing null termination");
+ }
+
+ public RegularExpression(bool critical, string regex)
+ : base(SignatureSubpacketTag.RegExp, critical, false, ToNullTerminatedUtf8ByteArray(regex))
+ {
+ }
+
+ public string Regex
+ {
+ // last byte is null terminator
+ get { return Strings.FromUtf8ByteArray(data, 0, data.Length - 1); }
+ }
+
+ public byte[] GetRawRegex() => Arrays.Clone(data);
+
+ private static byte[] ToNullTerminatedUtf8ByteArray(string str)
+ {
+ byte[] utf8 = Strings.ToUtf8ByteArray(str);
+ return Arrays.Append(utf8, 0x00);
+ }
+ }
+}
diff --git a/crypto/src/bcpg/sig/RevocationKey.cs b/crypto/src/bcpg/sig/RevocationKey.cs
index 11467d2af..e4ad4195b 100644
--- a/crypto/src/bcpg/sig/RevocationKey.cs
+++ b/crypto/src/bcpg/sig/RevocationKey.cs
@@ -12,28 +12,20 @@ namespace Org.BouncyCastle.Bcpg
// 1 octet of class,
// 1 octet of public-key algorithm ID,
// 20 octets of fingerprint
- public RevocationKey(
- bool isCritical,
- bool isLongLength,
- byte[] data)
+ public RevocationKey(bool isCritical, bool isLongLength, byte[] data)
: base(SignatureSubpacketTag.RevocationKey, isCritical, isLongLength, data)
{
}
- public RevocationKey(
- bool isCritical,
- RevocationKeyTag signatureClass,
- PublicKeyAlgorithmTag keyAlgorithm,
- byte[] fingerprint)
+ public RevocationKey(bool isCritical, RevocationKeyTag signatureClass, PublicKeyAlgorithmTag keyAlgorithm,
+ byte[] fingerprint)
: base(SignatureSubpacketTag.RevocationKey, isCritical, false,
CreateData(signatureClass, keyAlgorithm, fingerprint))
{
}
- private static byte[] CreateData(
- RevocationKeyTag signatureClass,
- PublicKeyAlgorithmTag keyAlgorithm,
- byte[] fingerprint)
+ private static byte[] CreateData(RevocationKeyTag signatureClass, PublicKeyAlgorithmTag keyAlgorithm,
+ byte[] fingerprint)
{
byte[] data = new byte[2 + fingerprint.Length];
data[0] = (byte)signatureClass;
@@ -44,17 +36,16 @@ namespace Org.BouncyCastle.Bcpg
public virtual RevocationKeyTag SignatureClass
{
- get { return (RevocationKeyTag)this.GetData()[0]; }
+ get { return (RevocationKeyTag)data[0]; }
}
public virtual PublicKeyAlgorithmTag Algorithm
{
- get { return (PublicKeyAlgorithmTag)this.GetData()[1]; }
+ get { return (PublicKeyAlgorithmTag)data[1]; }
}
public virtual byte[] GetFingerprint()
{
- byte[] data = this.GetData();
byte[] fingerprint = new byte[data.Length - 2];
Array.Copy(data, 2, fingerprint, 0, fingerprint.Length);
return fingerprint;
diff --git a/crypto/src/bcpg/sig/SignatureTarget.cs b/crypto/src/bcpg/sig/SignatureTarget.cs
new file mode 100644
index 000000000..c6a8dc574
--- /dev/null
+++ b/crypto/src/bcpg/sig/SignatureTarget.cs
@@ -0,0 +1,30 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * RFC 4880, Section 5.2.3.25 - Signature Target subpacket.
+ */
+ public class SignatureTarget
+ : SignatureSubpacket
+ {
+ public SignatureTarget(bool critical, bool isLongLength, byte[] data)
+ : base(SignatureSubpacketTag.SignatureTarget, critical, isLongLength, data)
+ {
+ }
+
+ public SignatureTarget(bool critical, int publicKeyAlgorithm, int hashAlgorithm, byte[] hashData)
+ : base(SignatureSubpacketTag.SignatureTarget, critical, false,
+ Arrays.Concatenate(new byte[]{ (byte)publicKeyAlgorithm, (byte)hashAlgorithm }, hashData))
+ {
+ }
+
+ public int PublicKeyAlgorithm => data[0];
+
+ public int HashAlgorithm => data[1];
+
+ public byte[] GetHashData() => Arrays.CopyOfRange(data, 2, data.Length);
+ }
+}
diff --git a/crypto/src/util/Strings.cs b/crypto/src/util/Strings.cs
index 29a95a07e..b1a63a3a1 100644
--- a/crypto/src/util/Strings.cs
+++ b/crypto/src/util/Strings.cs
@@ -78,6 +78,11 @@ namespace Org.BouncyCastle.Utilities
return Encoding.UTF8.GetString(bytes);
}
+ public static string FromUtf8ByteArray(byte[] bytes, int index, int count)
+ {
+ return Encoding.UTF8.GetString(bytes, index, count);
+ }
+
public static byte[] ToUtf8ByteArray(char[] cs)
{
return Encoding.UTF8.GetBytes(cs);
|