Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Cms/SignerInformation.cs
2025-10-09 09:57:24 +09:00

527 lines
17 KiB
C#

using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Cms;
public class SignerInformation
{
private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
private SignerID sid;
private Org.BouncyCastle.Asn1.Cms.SignerInfo info;
private AlgorithmIdentifier digestAlgorithm;
private AlgorithmIdentifier encryptionAlgorithm;
private readonly Asn1Set signedAttributeSet;
private readonly Asn1Set unsignedAttributeSet;
private CmsProcessable content;
private byte[] signature;
private DerObjectIdentifier contentType;
private IDigestCalculator digestCalculator;
private byte[] resultDigest;
private Org.BouncyCastle.Asn1.Cms.AttributeTable signedAttributeTable;
private Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttributeTable;
private readonly bool isCounterSignature;
public bool IsCounterSignature => isCounterSignature;
public DerObjectIdentifier ContentType => contentType;
public SignerID SignerID => sid;
public int Version => info.Version.Value.IntValue;
public AlgorithmIdentifier DigestAlgorithmID => digestAlgorithm;
public string DigestAlgOid => digestAlgorithm.Algorithm.Id;
public Asn1Object DigestAlgParams => digestAlgorithm.Parameters?.ToAsn1Object();
public AlgorithmIdentifier EncryptionAlgorithmID => encryptionAlgorithm;
public string EncryptionAlgOid => encryptionAlgorithm.Algorithm.Id;
public Asn1Object EncryptionAlgParams => encryptionAlgorithm.Parameters?.ToAsn1Object();
public Org.BouncyCastle.Asn1.Cms.AttributeTable SignedAttributes
{
get
{
if (signedAttributeSet != null && signedAttributeTable == null)
{
signedAttributeTable = new Org.BouncyCastle.Asn1.Cms.AttributeTable(signedAttributeSet);
}
return signedAttributeTable;
}
}
public Org.BouncyCastle.Asn1.Cms.AttributeTable UnsignedAttributes
{
get
{
if (unsignedAttributeSet != null && unsignedAttributeTable == null)
{
unsignedAttributeTable = new Org.BouncyCastle.Asn1.Cms.AttributeTable(unsignedAttributeSet);
}
return unsignedAttributeTable;
}
}
internal SignerInformation(Org.BouncyCastle.Asn1.Cms.SignerInfo info, DerObjectIdentifier contentType, CmsProcessable content, IDigestCalculator digestCalculator)
{
this.info = info;
sid = new SignerID();
this.contentType = contentType;
isCounterSignature = contentType == null;
try
{
SignerIdentifier signerID = info.SignerID;
if (signerID.IsTagged)
{
Asn1OctetString instance = Asn1OctetString.GetInstance(signerID.ID);
sid.SubjectKeyIdentifier = instance.GetEncoded();
}
else
{
Org.BouncyCastle.Asn1.Cms.IssuerAndSerialNumber instance2 = Org.BouncyCastle.Asn1.Cms.IssuerAndSerialNumber.GetInstance(signerID.ID);
sid.Issuer = instance2.Name;
sid.SerialNumber = instance2.SerialNumber.Value;
}
}
catch (IOException)
{
throw new ArgumentException("invalid sid in SignerInfo");
}
digestAlgorithm = info.DigestAlgorithm;
signedAttributeSet = info.AuthenticatedAttributes;
unsignedAttributeSet = info.UnauthenticatedAttributes;
encryptionAlgorithm = info.DigestEncryptionAlgorithm;
signature = info.EncryptedDigest.GetOctets();
this.content = content;
this.digestCalculator = digestCalculator;
}
protected SignerInformation(SignerInformation baseInfo)
{
info = baseInfo.info;
contentType = baseInfo.contentType;
isCounterSignature = baseInfo.IsCounterSignature;
sid = baseInfo.SignerID;
digestAlgorithm = info.DigestAlgorithm;
signedAttributeSet = info.AuthenticatedAttributes;
unsignedAttributeSet = info.UnauthenticatedAttributes;
encryptionAlgorithm = info.DigestEncryptionAlgorithm;
signature = info.EncryptedDigest.GetOctets();
content = baseInfo.content;
resultDigest = baseInfo.resultDigest;
signedAttributeTable = baseInfo.signedAttributeTable;
unsignedAttributeTable = baseInfo.unsignedAttributeTable;
}
public byte[] GetContentDigest()
{
if (resultDigest == null)
{
throw new InvalidOperationException("method can only be called after verify.");
}
return (byte[])resultDigest.Clone();
}
public byte[] GetSignature()
{
return (byte[])signature.Clone();
}
public SignerInformationStore GetCounterSignatures()
{
Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttributes = UnsignedAttributes;
if (unsignedAttributes == null)
{
return new SignerInformationStore(Platform.CreateArrayList(0));
}
IList list = Platform.CreateArrayList();
Asn1EncodableVector all = unsignedAttributes.GetAll(CmsAttributes.CounterSignature);
foreach (Org.BouncyCastle.Asn1.Cms.Attribute item in all)
{
Asn1Set attrValues = item.AttrValues;
_ = attrValues.Count;
_ = 1;
foreach (Asn1Encodable item2 in attrValues)
{
Org.BouncyCastle.Asn1.Cms.SignerInfo instance = Org.BouncyCastle.Asn1.Cms.SignerInfo.GetInstance(item2.ToAsn1Object());
string digestAlgName = CmsSignedHelper.Instance.GetDigestAlgName(instance.DigestAlgorithm.Algorithm.Id);
list.Add(new SignerInformation(instance, null, null, new CounterSignatureDigestCalculator(digestAlgName, GetSignature())));
}
}
return new SignerInformationStore(list);
}
public byte[] GetEncodedSignedAttributes()
{
if (signedAttributeSet != null)
{
return signedAttributeSet.GetEncoded("DER");
}
return null;
}
private bool DoVerify(AsymmetricKeyParameter key)
{
string digestAlgName = Helper.GetDigestAlgName(DigestAlgOid);
IDigest digestInstance = Helper.GetDigestInstance(digestAlgName);
DerObjectIdentifier algorithm = encryptionAlgorithm.Algorithm;
Asn1Encodable parameters = encryptionAlgorithm.Parameters;
ISigner signer;
if (algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
{
if (parameters == null)
{
throw new CmsException("RSASSA-PSS signature must specify algorithm parameters");
}
try
{
RsassaPssParameters instance = RsassaPssParameters.GetInstance(parameters.ToAsn1Object());
if (!instance.HashAlgorithm.Algorithm.Equals(digestAlgorithm.Algorithm))
{
throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm");
}
if (!instance.MaskGenAlgorithm.Algorithm.Equals(PkcsObjectIdentifiers.IdMgf1))
{
throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");
}
IDigest digest = DigestUtilities.GetDigest(instance.HashAlgorithm.Algorithm);
int intValue = instance.SaltLength.Value.IntValue;
byte b = (byte)instance.TrailerField.Value.IntValue;
if (b != 1)
{
throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1");
}
signer = new PssSigner(new RsaBlindedEngine(), digest, intValue);
}
catch (Exception e)
{
throw new CmsException("failed to set RSASSA-PSS signature parameters", e);
}
}
else
{
string algorithm2 = digestAlgName + "with" + Helper.GetEncryptionAlgName(EncryptionAlgOid);
signer = Helper.GetSignatureInstance(algorithm2);
}
try
{
if (digestCalculator != null)
{
resultDigest = digestCalculator.GetDigest();
}
else
{
if (content != null)
{
content.Write(new DigestSink(digestInstance));
}
else if (signedAttributeSet == null)
{
throw new CmsException("data not encapsulated in signature - use detached constructor.");
}
resultDigest = DigestUtilities.DoFinal(digestInstance);
}
}
catch (IOException e2)
{
throw new CmsException("can't process mime object to create signature.", e2);
}
Asn1Object singleValuedSignedAttribute = GetSingleValuedSignedAttribute(CmsAttributes.ContentType, "content-type");
if (singleValuedSignedAttribute == null)
{
if (!isCounterSignature && signedAttributeSet != null)
{
throw new CmsException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data");
}
}
else
{
if (isCounterSignature)
{
throw new CmsException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute");
}
if (!(singleValuedSignedAttribute is DerObjectIdentifier))
{
throw new CmsException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'");
}
DerObjectIdentifier derObjectIdentifier = (DerObjectIdentifier)singleValuedSignedAttribute;
if (!derObjectIdentifier.Equals(contentType))
{
throw new CmsException("content-type attribute value does not match eContentType");
}
}
Asn1Object singleValuedSignedAttribute2 = GetSingleValuedSignedAttribute(CmsAttributes.MessageDigest, "message-digest");
if (singleValuedSignedAttribute2 == null)
{
if (signedAttributeSet != null)
{
throw new CmsException("the message-digest signed attribute type MUST be present when there are any signed attributes present");
}
}
else
{
if (!(singleValuedSignedAttribute2 is Asn1OctetString))
{
throw new CmsException("message-digest attribute value not of ASN.1 type 'OCTET STRING'");
}
Asn1OctetString asn1OctetString = (Asn1OctetString)singleValuedSignedAttribute2;
if (!Arrays.AreEqual(resultDigest, asn1OctetString.GetOctets()))
{
throw new CmsException("message-digest attribute value does not match calculated value");
}
}
Org.BouncyCastle.Asn1.Cms.AttributeTable signedAttributes = SignedAttributes;
if (signedAttributes != null && signedAttributes.GetAll(CmsAttributes.CounterSignature).Count > 0)
{
throw new CmsException("A countersignature attribute MUST NOT be a signed attribute");
}
Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttributes = UnsignedAttributes;
if (unsignedAttributes != null)
{
foreach (Org.BouncyCastle.Asn1.Cms.Attribute item in unsignedAttributes.GetAll(CmsAttributes.CounterSignature))
{
if (item.AttrValues.Count < 1)
{
throw new CmsException("A countersignature attribute MUST contain at least one AttributeValue");
}
}
}
try
{
signer.Init(forSigning: false, key);
if (signedAttributeSet == null)
{
if (digestCalculator != null)
{
return VerifyDigest(resultDigest, key, GetSignature());
}
if (content != null)
{
try
{
content.Write(new SignerSink(signer));
}
catch (SignatureException ex)
{
throw new CmsStreamException("signature problem: " + ex);
}
}
}
else
{
byte[] encodedSignedAttributes = GetEncodedSignedAttributes();
signer.BlockUpdate(encodedSignedAttributes, 0, encodedSignedAttributes.Length);
}
return signer.VerifySignature(GetSignature());
}
catch (InvalidKeyException e3)
{
throw new CmsException("key not appropriate to signature in message.", e3);
}
catch (IOException e4)
{
throw new CmsException("can't process mime object to create signature.", e4);
}
catch (SignatureException ex2)
{
throw new CmsException("invalid signature format in message: " + ex2.Message, ex2);
}
}
private bool IsNull(Asn1Encodable o)
{
if (!(o is Asn1Null))
{
return o == null;
}
return true;
}
private DigestInfo DerDecode(byte[] encoding)
{
if (encoding[0] != 48)
{
throw new IOException("not a digest info object");
}
DigestInfo instance = DigestInfo.GetInstance(Asn1Object.FromByteArray(encoding));
if (instance.GetEncoded().Length != encoding.Length)
{
throw new CmsException("malformed RSA signature");
}
return instance;
}
private bool VerifyDigest(byte[] digest, AsymmetricKeyParameter key, byte[] signature)
{
string encryptionAlgName = Helper.GetEncryptionAlgName(EncryptionAlgOid);
try
{
if (encryptionAlgName.Equals("RSA"))
{
IBufferedCipher bufferedCipher = CmsEnvelopedHelper.Instance.CreateAsymmetricCipher("RSA/ECB/PKCS1Padding");
bufferedCipher.Init(forEncryption: false, key);
byte[] encoding = bufferedCipher.DoFinal(signature);
DigestInfo digestInfo = DerDecode(encoding);
if (!digestInfo.AlgorithmID.Algorithm.Equals(digestAlgorithm.Algorithm))
{
return false;
}
if (!IsNull(digestInfo.AlgorithmID.Parameters))
{
return false;
}
byte[] digest2 = digestInfo.GetDigest();
return Arrays.ConstantTimeAreEqual(digest, digest2);
}
if (encryptionAlgName.Equals("DSA"))
{
ISigner signer = SignerUtilities.GetSigner("NONEwithDSA");
signer.Init(forSigning: false, key);
signer.BlockUpdate(digest, 0, digest.Length);
return signer.VerifySignature(signature);
}
throw new CmsException("algorithm: " + encryptionAlgName + " not supported in base signatures.");
}
catch (SecurityUtilityException ex)
{
throw ex;
}
catch (GeneralSecurityException ex2)
{
throw new CmsException("Exception processing signature: " + ex2, ex2);
}
catch (IOException ex3)
{
throw new CmsException("Exception decoding signature: " + ex3, ex3);
}
}
public bool Verify(AsymmetricKeyParameter pubKey)
{
if (pubKey.IsPrivate)
{
throw new ArgumentException("Expected public key", "pubKey");
}
GetSigningTime();
return DoVerify(pubKey);
}
public bool Verify(X509Certificate cert)
{
Org.BouncyCastle.Asn1.Cms.Time signingTime = GetSigningTime();
if (signingTime != null)
{
cert.CheckValidity(signingTime.Date);
}
return DoVerify(cert.GetPublicKey());
}
public Org.BouncyCastle.Asn1.Cms.SignerInfo ToSignerInfo()
{
return info;
}
private Asn1Object GetSingleValuedSignedAttribute(DerObjectIdentifier attrOID, string printableName)
{
Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttributes = UnsignedAttributes;
if (unsignedAttributes != null && unsignedAttributes.GetAll(attrOID).Count > 0)
{
throw new CmsException("The " + printableName + " attribute MUST NOT be an unsigned attribute");
}
Org.BouncyCastle.Asn1.Cms.AttributeTable signedAttributes = SignedAttributes;
if (signedAttributes == null)
{
return null;
}
Asn1EncodableVector all = signedAttributes.GetAll(attrOID);
switch (all.Count)
{
case 0:
return null;
case 1:
{
Org.BouncyCastle.Asn1.Cms.Attribute attribute = (Org.BouncyCastle.Asn1.Cms.Attribute)all[0];
Asn1Set attrValues = attribute.AttrValues;
if (attrValues.Count != 1)
{
throw new CmsException("A " + printableName + " attribute MUST have a single attribute value");
}
return attrValues[0].ToAsn1Object();
}
default:
throw new CmsException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the " + printableName + " attribute");
}
}
private Org.BouncyCastle.Asn1.Cms.Time GetSigningTime()
{
Asn1Object singleValuedSignedAttribute = GetSingleValuedSignedAttribute(CmsAttributes.SigningTime, "signing-time");
if (singleValuedSignedAttribute == null)
{
return null;
}
try
{
return Org.BouncyCastle.Asn1.Cms.Time.GetInstance(singleValuedSignedAttribute);
}
catch (ArgumentException)
{
throw new CmsException("signing-time attribute value not a valid 'Time' structure");
}
}
public static SignerInformation ReplaceUnsignedAttributes(SignerInformation signerInformation, Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttributes)
{
Org.BouncyCastle.Asn1.Cms.SignerInfo signerInfo = signerInformation.info;
Asn1Set unauthenticatedAttributes = null;
if (unsignedAttributes != null)
{
unauthenticatedAttributes = new DerSet(unsignedAttributes.ToAsn1EncodableVector());
}
return new SignerInformation(new Org.BouncyCastle.Asn1.Cms.SignerInfo(signerInfo.SignerID, signerInfo.DigestAlgorithm, signerInfo.AuthenticatedAttributes, signerInfo.DigestEncryptionAlgorithm, signerInfo.EncryptedDigest, unauthenticatedAttributes), signerInformation.contentType, signerInformation.content, null);
}
public static SignerInformation AddCounterSigners(SignerInformation signerInformation, SignerInformationStore counterSigners)
{
Org.BouncyCastle.Asn1.Cms.SignerInfo signerInfo = signerInformation.info;
Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttributes = signerInformation.UnsignedAttributes;
Asn1EncodableVector asn1EncodableVector = ((unsignedAttributes == null) ? new Asn1EncodableVector() : unsignedAttributes.ToAsn1EncodableVector());
Asn1EncodableVector asn1EncodableVector2 = new Asn1EncodableVector();
foreach (SignerInformation signer in counterSigners.GetSigners())
{
asn1EncodableVector2.Add(signer.ToSignerInfo());
}
asn1EncodableVector.Add(new Org.BouncyCastle.Asn1.Cms.Attribute(CmsAttributes.CounterSignature, new DerSet(asn1EncodableVector2)));
return new SignerInformation(new Org.BouncyCastle.Asn1.Cms.SignerInfo(signerInfo.SignerID, signerInfo.DigestAlgorithm, signerInfo.AuthenticatedAttributes, signerInfo.DigestEncryptionAlgorithm, signerInfo.EncryptedDigest, new DerSet(asn1EncodableVector)), signerInformation.contentType, signerInformation.content, null);
}
}