init commit
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class AuthenticatorControl : IControl
|
||||
{
|
||||
private static readonly DerObjectIdentifier type = CrmfObjectIdentifiers.id_regCtrl_authenticator;
|
||||
|
||||
private readonly DerUtf8String token;
|
||||
|
||||
public DerObjectIdentifier Type => type;
|
||||
|
||||
public Asn1Encodable Value => token;
|
||||
|
||||
public AuthenticatorControl(DerUtf8String token)
|
||||
{
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public AuthenticatorControl(string token)
|
||||
{
|
||||
this.token = new DerUtf8String(token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Operators;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class CertificateRequestMessage
|
||||
{
|
||||
public static readonly int popRaVerified = 0;
|
||||
|
||||
public static readonly int popSigningKey = 1;
|
||||
|
||||
public static readonly int popKeyEncipherment = 2;
|
||||
|
||||
public static readonly int popKeyAgreement = 3;
|
||||
|
||||
private readonly CertReqMsg certReqMsg;
|
||||
|
||||
private readonly Controls controls;
|
||||
|
||||
public bool HasControls => controls != null;
|
||||
|
||||
public bool HasProofOfPossession => certReqMsg.Popo != null;
|
||||
|
||||
public int ProofOfPossession => certReqMsg.Popo.Type;
|
||||
|
||||
public bool HasSigningKeyProofOfPossessionWithPkMac
|
||||
{
|
||||
get
|
||||
{
|
||||
ProofOfPossession popo = certReqMsg.Popo;
|
||||
if (popo.Type == popSigningKey)
|
||||
{
|
||||
PopoSigningKey instance = PopoSigningKey.GetInstance(popo.Object);
|
||||
return instance.PoposkInput.PublicKeyMac != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static CertReqMsg ParseBytes(byte[] encoding)
|
||||
{
|
||||
return CertReqMsg.GetInstance(encoding);
|
||||
}
|
||||
|
||||
public CertificateRequestMessage(byte[] encoded)
|
||||
: this(CertReqMsg.GetInstance(encoded))
|
||||
{
|
||||
}
|
||||
|
||||
public CertificateRequestMessage(CertReqMsg certReqMsg)
|
||||
{
|
||||
this.certReqMsg = certReqMsg;
|
||||
controls = certReqMsg.CertReq.Controls;
|
||||
}
|
||||
|
||||
public CertReqMsg ToAsn1Structure()
|
||||
{
|
||||
return certReqMsg;
|
||||
}
|
||||
|
||||
public CertTemplate GetCertTemplate()
|
||||
{
|
||||
return certReqMsg.CertReq.CertTemplate;
|
||||
}
|
||||
|
||||
public bool HasControl(DerObjectIdentifier objectIdentifier)
|
||||
{
|
||||
return FindControl(objectIdentifier) != null;
|
||||
}
|
||||
|
||||
public IControl GetControl(DerObjectIdentifier type)
|
||||
{
|
||||
AttributeTypeAndValue attributeTypeAndValue = FindControl(type);
|
||||
if (attributeTypeAndValue != null)
|
||||
{
|
||||
if (attributeTypeAndValue.Type.Equals(CrmfObjectIdentifiers.id_regCtrl_pkiArchiveOptions))
|
||||
{
|
||||
return new PkiArchiveControl(PkiArchiveOptions.GetInstance(attributeTypeAndValue.Value));
|
||||
}
|
||||
if (attributeTypeAndValue.Type.Equals(CrmfObjectIdentifiers.id_regCtrl_regToken))
|
||||
{
|
||||
return new RegTokenControl(DerUtf8String.GetInstance(attributeTypeAndValue.Value));
|
||||
}
|
||||
if (attributeTypeAndValue.Type.Equals(CrmfObjectIdentifiers.id_regCtrl_authenticator))
|
||||
{
|
||||
return new AuthenticatorControl(DerUtf8String.GetInstance(attributeTypeAndValue.Value));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AttributeTypeAndValue FindControl(DerObjectIdentifier type)
|
||||
{
|
||||
if (controls == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
AttributeTypeAndValue[] array = controls.ToAttributeTypeAndValueArray();
|
||||
AttributeTypeAndValue result = null;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (array[i].Type.Equals(type))
|
||||
{
|
||||
result = array[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IsValidSigningKeyPop(IVerifierFactoryProvider verifierProvider)
|
||||
{
|
||||
ProofOfPossession popo = certReqMsg.Popo;
|
||||
if (popo.Type == popSigningKey)
|
||||
{
|
||||
PopoSigningKey instance = PopoSigningKey.GetInstance(popo.Object);
|
||||
if (instance.PoposkInput != null && instance.PoposkInput.PublicKeyMac != null)
|
||||
{
|
||||
throw new InvalidOperationException("verification requires password check");
|
||||
}
|
||||
return verifySignature(verifierProvider, instance);
|
||||
}
|
||||
throw new InvalidOperationException("not Signing Key type of proof of possession");
|
||||
}
|
||||
|
||||
private bool verifySignature(IVerifierFactoryProvider verifierFactoryProvider, PopoSigningKey signKey)
|
||||
{
|
||||
IStreamCalculator streamCalculator;
|
||||
try
|
||||
{
|
||||
IVerifierFactory verifierFactory = verifierFactoryProvider.CreateVerifierFactory(signKey.AlgorithmIdentifier);
|
||||
streamCalculator = verifierFactory.CreateCalculator();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new CrmfException("unable to create verifier: " + ex.Message, ex);
|
||||
}
|
||||
if (signKey.PoposkInput != null)
|
||||
{
|
||||
byte[] derEncoded = signKey.GetDerEncoded();
|
||||
streamCalculator.Stream.Write(derEncoded, 0, derEncoded.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] derEncoded2 = certReqMsg.CertReq.GetDerEncoded();
|
||||
streamCalculator.Stream.Write(derEncoded2, 0, derEncoded2.Length);
|
||||
}
|
||||
DefaultVerifierResult defaultVerifierResult = (DefaultVerifierResult)streamCalculator.GetResult();
|
||||
return defaultVerifierResult.IsVerified(signKey.Signature.GetBytes());
|
||||
}
|
||||
|
||||
public byte[] GetEncoded()
|
||||
{
|
||||
return certReqMsg.GetEncoded();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class CertificateRequestMessageBuilder
|
||||
{
|
||||
private readonly BigInteger _certReqId;
|
||||
|
||||
private X509ExtensionsGenerator _extGenerator;
|
||||
|
||||
private CertTemplateBuilder _templateBuilder;
|
||||
|
||||
private IList _controls = Platform.CreateArrayList();
|
||||
|
||||
private ISignatureFactory _popSigner;
|
||||
|
||||
private PKMacBuilder _pkMacBuilder;
|
||||
|
||||
private char[] _password;
|
||||
|
||||
private GeneralName _sender;
|
||||
|
||||
private int _popoType = 2;
|
||||
|
||||
private PopoPrivKey _popoPrivKey;
|
||||
|
||||
private Asn1Null _popRaVerified;
|
||||
|
||||
private PKMacValue _agreeMac;
|
||||
|
||||
public CertificateRequestMessageBuilder(BigInteger certReqId)
|
||||
{
|
||||
_certReqId = certReqId;
|
||||
_extGenerator = new X509ExtensionsGenerator();
|
||||
_templateBuilder = new CertTemplateBuilder();
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetPublicKey(SubjectPublicKeyInfo publicKeyInfo)
|
||||
{
|
||||
if (publicKeyInfo != null)
|
||||
{
|
||||
_templateBuilder.SetPublicKey(publicKeyInfo);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetIssuer(X509Name issuer)
|
||||
{
|
||||
if (issuer != null)
|
||||
{
|
||||
_templateBuilder.SetIssuer(issuer);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetSubject(X509Name subject)
|
||||
{
|
||||
if (subject != null)
|
||||
{
|
||||
_templateBuilder.SetSubject(subject);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetSerialNumber(BigInteger serialNumber)
|
||||
{
|
||||
if (serialNumber != null)
|
||||
{
|
||||
_templateBuilder.SetSerialNumber(new DerInteger(serialNumber));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetValidity(Time notBefore, Time notAfter)
|
||||
{
|
||||
_templateBuilder.SetValidity(new OptionalValidity(notBefore, notAfter));
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder AddExtension(DerObjectIdentifier oid, bool critical, Asn1Encodable value)
|
||||
{
|
||||
_extGenerator.AddExtension(oid, critical, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder AddExtension(DerObjectIdentifier oid, bool critical, byte[] value)
|
||||
{
|
||||
_extGenerator.AddExtension(oid, critical, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder AddControl(IControl control)
|
||||
{
|
||||
_controls.Add(control);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetProofOfPossessionSignKeySigner(ISignatureFactory popoSignatureFactory)
|
||||
{
|
||||
if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
|
||||
{
|
||||
throw new InvalidOperationException("only one proof of possession is allowed.");
|
||||
}
|
||||
_popSigner = popoSignatureFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetProofOfPossessionSubsequentMessage(SubsequentMessage msg)
|
||||
{
|
||||
if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
|
||||
{
|
||||
throw new InvalidOperationException("only one proof of possession is allowed.");
|
||||
}
|
||||
_popoType = 2;
|
||||
_popoPrivKey = new PopoPrivKey(msg);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetProofOfPossessionSubsequentMessage(int type, SubsequentMessage msg)
|
||||
{
|
||||
if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
|
||||
{
|
||||
throw new InvalidOperationException("only one proof of possession is allowed.");
|
||||
}
|
||||
if (type != 2 && type != 3)
|
||||
{
|
||||
throw new ArgumentException("type must be ProofOfPossession.TYPE_KEY_ENCIPHERMENT || ProofOfPossession.TYPE_KEY_AGREEMENT");
|
||||
}
|
||||
_popoType = type;
|
||||
_popoPrivKey = new PopoPrivKey(msg);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetProofOfPossessionAgreeMac(PKMacValue macValue)
|
||||
{
|
||||
if (_popSigner != null || _popRaVerified != null || _popoPrivKey != null)
|
||||
{
|
||||
throw new InvalidOperationException("only one proof of possession allowed");
|
||||
}
|
||||
_agreeMac = macValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetProofOfPossessionRaVerified()
|
||||
{
|
||||
if (_popSigner != null || _popoPrivKey != null)
|
||||
{
|
||||
throw new InvalidOperationException("only one proof of possession allowed");
|
||||
}
|
||||
_popRaVerified = DerNull.Instance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetAuthInfoPKMAC(PKMacBuilder pkmacFactory, char[] password)
|
||||
{
|
||||
_pkMacBuilder = pkmacFactory;
|
||||
_password = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetAuthInfoSender(X509Name sender)
|
||||
{
|
||||
return SetAuthInfoSender(new GeneralName(sender));
|
||||
}
|
||||
|
||||
public CertificateRequestMessageBuilder SetAuthInfoSender(GeneralName sender)
|
||||
{
|
||||
_sender = sender;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CertificateRequestMessage Build()
|
||||
{
|
||||
Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(new DerInteger(_certReqId));
|
||||
if (!_extGenerator.IsEmpty)
|
||||
{
|
||||
_templateBuilder.SetExtensions(_extGenerator.Generate());
|
||||
}
|
||||
asn1EncodableVector.Add(_templateBuilder.Build());
|
||||
if (_controls.Count > 0)
|
||||
{
|
||||
Asn1EncodableVector asn1EncodableVector2 = new Asn1EncodableVector();
|
||||
foreach (object control2 in _controls)
|
||||
{
|
||||
IControl control = (IControl)control2;
|
||||
asn1EncodableVector2.Add(new AttributeTypeAndValue(control.Type, control.Value));
|
||||
}
|
||||
asn1EncodableVector.Add(new DerSequence(asn1EncodableVector2));
|
||||
}
|
||||
CertRequest instance = CertRequest.GetInstance(new DerSequence(asn1EncodableVector));
|
||||
asn1EncodableVector = new Asn1EncodableVector(instance);
|
||||
if (_popSigner != null)
|
||||
{
|
||||
CertTemplate certTemplate = instance.CertTemplate;
|
||||
if (certTemplate.Subject == null || certTemplate.PublicKey == null)
|
||||
{
|
||||
SubjectPublicKeyInfo publicKey = instance.CertTemplate.PublicKey;
|
||||
ProofOfPossessionSigningKeyBuilder proofOfPossessionSigningKeyBuilder = new ProofOfPossessionSigningKeyBuilder(publicKey);
|
||||
if (_sender != null)
|
||||
{
|
||||
proofOfPossessionSigningKeyBuilder.SetSender(_sender);
|
||||
}
|
||||
else
|
||||
{
|
||||
proofOfPossessionSigningKeyBuilder.SetPublicKeyMac(_pkMacBuilder, _password);
|
||||
}
|
||||
asn1EncodableVector.Add(new ProofOfPossession(proofOfPossessionSigningKeyBuilder.Build(_popSigner)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ProofOfPossessionSigningKeyBuilder proofOfPossessionSigningKeyBuilder2 = new ProofOfPossessionSigningKeyBuilder(instance);
|
||||
asn1EncodableVector.Add(new ProofOfPossession(proofOfPossessionSigningKeyBuilder2.Build(_popSigner)));
|
||||
}
|
||||
}
|
||||
else if (_popoPrivKey != null)
|
||||
{
|
||||
asn1EncodableVector.Add(new ProofOfPossession(_popoType, _popoPrivKey));
|
||||
}
|
||||
else if (_agreeMac != null)
|
||||
{
|
||||
asn1EncodableVector.Add(new ProofOfPossession(3, PopoPrivKey.GetInstance(new DerTaggedObject(explicitly: false, 3, _agreeMac), isExplicit: true)));
|
||||
}
|
||||
else if (_popRaVerified != null)
|
||||
{
|
||||
asn1EncodableVector.Add(new ProofOfPossession());
|
||||
}
|
||||
return new CertificateRequestMessage(CertReqMsg.GetInstance(new DerSequence(asn1EncodableVector)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class CrmfException : Exception
|
||||
{
|
||||
public CrmfException()
|
||||
{
|
||||
}
|
||||
|
||||
public CrmfException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public CrmfException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class DefaultPKMacPrimitivesProvider : IPKMacPrimitivesProvider
|
||||
{
|
||||
public IDigest CreateDigest(AlgorithmIdentifier digestAlg)
|
||||
{
|
||||
return DigestUtilities.GetDigest(digestAlg.Algorithm);
|
||||
}
|
||||
|
||||
public IMac CreateMac(AlgorithmIdentifier macAlg)
|
||||
{
|
||||
return MacUtilities.GetMac(macAlg.Algorithm);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Org.BouncyCastle.Crypto;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
internal class DefaultPKMacResult : IBlockResult
|
||||
{
|
||||
private readonly IMac mac;
|
||||
|
||||
public DefaultPKMacResult(IMac mac)
|
||||
{
|
||||
this.mac = mac;
|
||||
}
|
||||
|
||||
public byte[] Collect()
|
||||
{
|
||||
byte[] array = new byte[mac.GetMacSize()];
|
||||
mac.DoFinal(array, 0);
|
||||
return array;
|
||||
}
|
||||
|
||||
public int Collect(byte[] sig, int sigOff)
|
||||
{
|
||||
byte[] array = Collect();
|
||||
array.CopyTo(sig, sigOff);
|
||||
return array.Length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.IO;
|
||||
using Org.BouncyCastle.X509;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class EncryptedValueBuilder
|
||||
{
|
||||
private readonly IKeyWrapper wrapper;
|
||||
|
||||
private readonly ICipherBuilderWithKey encryptor;
|
||||
|
||||
private readonly IEncryptedValuePadder padder;
|
||||
|
||||
public EncryptedValueBuilder(IKeyWrapper wrapper, ICipherBuilderWithKey encryptor)
|
||||
: this(wrapper, encryptor, null)
|
||||
{
|
||||
}
|
||||
|
||||
public EncryptedValueBuilder(IKeyWrapper wrapper, ICipherBuilderWithKey encryptor, IEncryptedValuePadder padder)
|
||||
{
|
||||
this.wrapper = wrapper;
|
||||
this.encryptor = encryptor;
|
||||
this.padder = padder;
|
||||
}
|
||||
|
||||
public EncryptedValue Build(char[] revocationPassphrase)
|
||||
{
|
||||
return EncryptData(PadData(Strings.ToUtf8ByteArray(revocationPassphrase)));
|
||||
}
|
||||
|
||||
public EncryptedValue Build(X509Certificate holder)
|
||||
{
|
||||
try
|
||||
{
|
||||
return EncryptData(PadData(holder.GetEncoded()));
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new CrmfException("cannot encode certificate: " + ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public EncryptedValue Build(PrivateKeyInfo privateKeyInfo)
|
||||
{
|
||||
Pkcs8EncryptedPrivateKeyInfoBuilder pkcs8EncryptedPrivateKeyInfoBuilder = new Pkcs8EncryptedPrivateKeyInfoBuilder(privateKeyInfo);
|
||||
AlgorithmIdentifier privateKeyAlgorithm = privateKeyInfo.PrivateKeyAlgorithm;
|
||||
AlgorithmIdentifier symmAlg = (AlgorithmIdentifier)encryptor.AlgorithmDetails;
|
||||
try
|
||||
{
|
||||
Pkcs8EncryptedPrivateKeyInfo pkcs8EncryptedPrivateKeyInfo = pkcs8EncryptedPrivateKeyInfoBuilder.Build(encryptor);
|
||||
DerBitString encSymmKey = new DerBitString(wrapper.Wrap(((KeyParameter)encryptor.Key).GetKey()).Collect());
|
||||
AlgorithmIdentifier keyAlg = (AlgorithmIdentifier)wrapper.AlgorithmDetails;
|
||||
Asn1OctetString valueHint = null;
|
||||
return new EncryptedValue(privateKeyAlgorithm, symmAlg, encSymmKey, keyAlg, valueHint, new DerBitString(pkcs8EncryptedPrivateKeyInfo.GetEncryptedData()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new CrmfException("cannot wrap key: " + ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private EncryptedValue EncryptData(byte[] data)
|
||||
{
|
||||
MemoryOutputStream memoryOutputStream = new MemoryOutputStream();
|
||||
Stream stream = encryptor.BuildCipher(memoryOutputStream).Stream;
|
||||
try
|
||||
{
|
||||
stream.Write(data, 0, data.Length);
|
||||
stream.Close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new CrmfException("cannot process data: " + ex.Message, ex);
|
||||
}
|
||||
AlgorithmIdentifier intendedAlg = null;
|
||||
AlgorithmIdentifier symmAlg = (AlgorithmIdentifier)encryptor.AlgorithmDetails;
|
||||
DerBitString encSymmKey;
|
||||
try
|
||||
{
|
||||
encSymmKey = new DerBitString(wrapper.Wrap(((KeyParameter)encryptor.Key).GetKey()).Collect());
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
throw new CrmfException("cannot wrap key: " + ex2.Message, ex2);
|
||||
}
|
||||
AlgorithmIdentifier keyAlg = (AlgorithmIdentifier)wrapper.AlgorithmDetails;
|
||||
Asn1OctetString valueHint = null;
|
||||
DerBitString encValue = new DerBitString(memoryOutputStream.ToArray());
|
||||
return new EncryptedValue(intendedAlg, symmAlg, encSymmKey, keyAlg, valueHint, encValue);
|
||||
}
|
||||
|
||||
private byte[] PadData(byte[] data)
|
||||
{
|
||||
if (padder != null)
|
||||
{
|
||||
return padder.GetPaddedData(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public interface IControl
|
||||
{
|
||||
DerObjectIdentifier Type { get; }
|
||||
|
||||
Asn1Encodable Value { get; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public interface IEncryptedValuePadder
|
||||
{
|
||||
byte[] GetPaddedData(byte[] data);
|
||||
|
||||
byte[] GetUnpaddedData(byte[] paddedData);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public interface IPKMacPrimitivesProvider
|
||||
{
|
||||
IDigest CreateDigest(AlgorithmIdentifier digestAlg);
|
||||
|
||||
IMac CreateMac(AlgorithmIdentifier macAlg);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Cmp;
|
||||
using Org.BouncyCastle.Asn1.Iana;
|
||||
using Org.BouncyCastle.Asn1.Oiw;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class PKMacBuilder
|
||||
{
|
||||
private AlgorithmIdentifier owf;
|
||||
|
||||
private AlgorithmIdentifier mac;
|
||||
|
||||
private IPKMacPrimitivesProvider provider;
|
||||
|
||||
private SecureRandom random;
|
||||
|
||||
private PbmParameter parameters;
|
||||
|
||||
private int iterationCount;
|
||||
|
||||
private int saltLength;
|
||||
|
||||
private byte[] salt;
|
||||
|
||||
private int maxIterations;
|
||||
|
||||
public PKMacBuilder()
|
||||
: this(new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1), 1000, new AlgorithmIdentifier(IanaObjectIdentifiers.HmacSha1, DerNull.Instance), new DefaultPKMacPrimitivesProvider())
|
||||
{
|
||||
}
|
||||
|
||||
public PKMacBuilder(IPKMacPrimitivesProvider provider)
|
||||
: this(new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1), 1000, new AlgorithmIdentifier(IanaObjectIdentifiers.HmacSha1, DerNull.Instance), provider)
|
||||
{
|
||||
}
|
||||
|
||||
public PKMacBuilder(IPKMacPrimitivesProvider provider, AlgorithmIdentifier digestAlgorithmIdentifier, AlgorithmIdentifier macAlgorithmIdentifier)
|
||||
: this(digestAlgorithmIdentifier, 1000, macAlgorithmIdentifier, provider)
|
||||
{
|
||||
}
|
||||
|
||||
public PKMacBuilder(IPKMacPrimitivesProvider provider, int maxIterations)
|
||||
{
|
||||
this.provider = provider;
|
||||
this.maxIterations = maxIterations;
|
||||
}
|
||||
|
||||
private PKMacBuilder(AlgorithmIdentifier digestAlgorithmIdentifier, int iterationCount, AlgorithmIdentifier macAlgorithmIdentifier, IPKMacPrimitivesProvider provider)
|
||||
{
|
||||
this.iterationCount = iterationCount;
|
||||
mac = macAlgorithmIdentifier;
|
||||
owf = digestAlgorithmIdentifier;
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public PKMacBuilder SetSaltLength(int saltLength)
|
||||
{
|
||||
if (saltLength < 8)
|
||||
{
|
||||
throw new ArgumentException("salt length must be at least 8 bytes");
|
||||
}
|
||||
this.saltLength = saltLength;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PKMacBuilder SetIterationCount(int iterationCount)
|
||||
{
|
||||
if (iterationCount < 100)
|
||||
{
|
||||
throw new ArgumentException("iteration count must be at least 100");
|
||||
}
|
||||
CheckIterationCountCeiling(iterationCount);
|
||||
this.iterationCount = iterationCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PKMacBuilder SetParameters(PbmParameter parameters)
|
||||
{
|
||||
CheckIterationCountCeiling(parameters.IterationCount.Value.IntValue);
|
||||
this.parameters = parameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PKMacBuilder SetSecureRandom(SecureRandom random)
|
||||
{
|
||||
this.random = random;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IMacFactory Build(char[] password)
|
||||
{
|
||||
if (parameters != null)
|
||||
{
|
||||
return GenCalculator(parameters, password);
|
||||
}
|
||||
byte[] buffer = new byte[saltLength];
|
||||
if (random == null)
|
||||
{
|
||||
random = new SecureRandom();
|
||||
}
|
||||
random.NextBytes(buffer);
|
||||
return GenCalculator(new PbmParameter(buffer, owf, iterationCount, mac), password);
|
||||
}
|
||||
|
||||
private void CheckIterationCountCeiling(int iterationCount)
|
||||
{
|
||||
if (maxIterations > 0 && iterationCount > maxIterations)
|
||||
{
|
||||
throw new ArgumentException("iteration count exceeds limit (" + iterationCount + " > " + maxIterations + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private IMacFactory GenCalculator(PbmParameter parameters, char[] password)
|
||||
{
|
||||
byte[] array = Strings.ToUtf8ByteArray(password);
|
||||
byte[] octets = parameters.Salt.GetOctets();
|
||||
byte[] array2 = new byte[array.Length + octets.Length];
|
||||
Array.Copy(array, 0, array2, 0, array.Length);
|
||||
Array.Copy(octets, 0, array2, array.Length, octets.Length);
|
||||
IDigest digest = provider.CreateDigest(parameters.Owf);
|
||||
int num = parameters.IterationCount.Value.IntValue;
|
||||
digest.BlockUpdate(array2, 0, array2.Length);
|
||||
array2 = new byte[digest.GetDigestSize()];
|
||||
digest.DoFinal(array2, 0);
|
||||
while (--num > 0)
|
||||
{
|
||||
digest.BlockUpdate(array2, 0, array2.Length);
|
||||
digest.DoFinal(array2, 0);
|
||||
}
|
||||
byte[] key = array2;
|
||||
return new PKMacFactory(key, parameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Org.BouncyCastle.Asn1.Cmp;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
internal class PKMacFactory : IMacFactory
|
||||
{
|
||||
protected readonly PbmParameter parameters;
|
||||
|
||||
private readonly byte[] key;
|
||||
|
||||
public virtual object AlgorithmDetails => new AlgorithmIdentifier(CmpObjectIdentifiers.passwordBasedMac, parameters);
|
||||
|
||||
public PKMacFactory(byte[] key, PbmParameter parameters)
|
||||
{
|
||||
this.key = Arrays.Clone(key);
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public virtual IStreamCalculator CreateCalculator()
|
||||
{
|
||||
IMac mac = MacUtilities.GetMac(parameters.Mac.Algorithm);
|
||||
mac.Init(new KeyParameter(key));
|
||||
return new PKMacStreamCalculator(mac);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.IO;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
internal class PKMacStreamCalculator : IStreamCalculator
|
||||
{
|
||||
private readonly MacSink _stream;
|
||||
|
||||
public Stream Stream => _stream;
|
||||
|
||||
public PKMacStreamCalculator(IMac mac)
|
||||
{
|
||||
_stream = new MacSink(mac);
|
||||
}
|
||||
|
||||
public object GetResult()
|
||||
{
|
||||
return new DefaultPKMacResult(_stream.Mac);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Cms;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
using Org.BouncyCastle.Cms;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class PkiArchiveControl : IControl
|
||||
{
|
||||
public static readonly int encryptedPrivKey = 0;
|
||||
|
||||
public static readonly int keyGenParameters = 1;
|
||||
|
||||
public static readonly int archiveRemGenPrivKey = 2;
|
||||
|
||||
private static readonly DerObjectIdentifier type = CrmfObjectIdentifiers.id_regCtrl_pkiArchiveOptions;
|
||||
|
||||
private readonly PkiArchiveOptions pkiArchiveOptions;
|
||||
|
||||
public DerObjectIdentifier Type => type;
|
||||
|
||||
public Asn1Encodable Value => pkiArchiveOptions;
|
||||
|
||||
public int ArchiveType => pkiArchiveOptions.Type;
|
||||
|
||||
public bool EnvelopedData
|
||||
{
|
||||
get
|
||||
{
|
||||
EncryptedKey instance = EncryptedKey.GetInstance(pkiArchiveOptions.Value);
|
||||
return !instance.IsEncryptedValue;
|
||||
}
|
||||
}
|
||||
|
||||
public PkiArchiveControl(PkiArchiveOptions pkiArchiveOptions)
|
||||
{
|
||||
this.pkiArchiveOptions = pkiArchiveOptions;
|
||||
}
|
||||
|
||||
public CmsEnvelopedData GetEnvelopedData()
|
||||
{
|
||||
try
|
||||
{
|
||||
EncryptedKey instance = EncryptedKey.GetInstance(pkiArchiveOptions.Value);
|
||||
EnvelopedData instance2 = Org.BouncyCastle.Asn1.Cms.EnvelopedData.GetInstance(instance.Value);
|
||||
return new CmsEnvelopedData(new ContentInfo(CmsObjectIdentifiers.EnvelopedData, instance2));
|
||||
}
|
||||
catch (CmsException ex)
|
||||
{
|
||||
throw new CrmfException("CMS parsing error: " + ex.Message, ex);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
throw new CrmfException("CRMF parsing error: " + ex2.Message, ex2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1.Cms;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Cms;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class PkiArchiveControlBuilder
|
||||
{
|
||||
private CmsEnvelopedDataGenerator envGen;
|
||||
|
||||
private CmsProcessableByteArray keyContent;
|
||||
|
||||
public PkiArchiveControlBuilder(PrivateKeyInfo privateKeyInfo, GeneralName generalName)
|
||||
{
|
||||
EncKeyWithID encKeyWithID = new EncKeyWithID(privateKeyInfo, generalName);
|
||||
try
|
||||
{
|
||||
keyContent = new CmsProcessableByteArray(CrmfObjectIdentifiers.id_ct_encKeyWithID, encKeyWithID.GetEncoded());
|
||||
}
|
||||
catch (IOException innerException)
|
||||
{
|
||||
throw new InvalidOperationException("unable to encode key and general name info", innerException);
|
||||
}
|
||||
envGen = new CmsEnvelopedDataGenerator();
|
||||
}
|
||||
|
||||
public PkiArchiveControlBuilder AddRecipientGenerator(RecipientInfoGenerator recipientGen)
|
||||
{
|
||||
envGen.AddRecipientInfoGenerator(recipientGen);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PkiArchiveControl Build(ICipherBuilderWithKey contentEncryptor)
|
||||
{
|
||||
CmsEnvelopedData cmsEnvelopedData = envGen.Generate(keyContent, contentEncryptor);
|
||||
EnvelopedData instance = EnvelopedData.GetInstance(cmsEnvelopedData.ContentInfo.Content);
|
||||
return new PkiArchiveControl(new PkiArchiveOptions(new EncryptedKey(instance)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Operators;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class ProofOfPossessionSigningKeyBuilder
|
||||
{
|
||||
private CertRequest _certRequest;
|
||||
|
||||
private SubjectPublicKeyInfo _pubKeyInfo;
|
||||
|
||||
private GeneralName _name;
|
||||
|
||||
private PKMacValue _publicKeyMAC;
|
||||
|
||||
public ProofOfPossessionSigningKeyBuilder(CertRequest certRequest)
|
||||
{
|
||||
_certRequest = certRequest;
|
||||
}
|
||||
|
||||
public ProofOfPossessionSigningKeyBuilder(SubjectPublicKeyInfo pubKeyInfo)
|
||||
{
|
||||
_pubKeyInfo = pubKeyInfo;
|
||||
}
|
||||
|
||||
public ProofOfPossessionSigningKeyBuilder SetSender(GeneralName name)
|
||||
{
|
||||
_name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProofOfPossessionSigningKeyBuilder SetPublicKeyMac(PKMacBuilder generator, char[] password)
|
||||
{
|
||||
IMacFactory macFactory = generator.Build(password);
|
||||
IStreamCalculator streamCalculator = macFactory.CreateCalculator();
|
||||
byte[] derEncoded = _pubKeyInfo.GetDerEncoded();
|
||||
streamCalculator.Stream.Write(derEncoded, 0, derEncoded.Length);
|
||||
streamCalculator.Stream.Flush();
|
||||
streamCalculator.Stream.Close();
|
||||
_publicKeyMAC = new PKMacValue((AlgorithmIdentifier)macFactory.AlgorithmDetails, new DerBitString(((IBlockResult)streamCalculator.GetResult()).Collect()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public PopoSigningKey Build(ISignatureFactory signer)
|
||||
{
|
||||
if (_name != null && _publicKeyMAC != null)
|
||||
{
|
||||
throw new InvalidOperationException("name and publicKeyMAC cannot both be set.");
|
||||
}
|
||||
IStreamCalculator streamCalculator = signer.CreateCalculator();
|
||||
PopoSigningKeyInput popoSigningKeyInput;
|
||||
if (_certRequest != null)
|
||||
{
|
||||
popoSigningKeyInput = null;
|
||||
byte[] derEncoded = _certRequest.GetDerEncoded();
|
||||
streamCalculator.Stream.Write(derEncoded, 0, derEncoded.Length);
|
||||
}
|
||||
else if (_name != null)
|
||||
{
|
||||
popoSigningKeyInput = new PopoSigningKeyInput(_name, _pubKeyInfo);
|
||||
byte[] derEncoded = popoSigningKeyInput.GetDerEncoded();
|
||||
streamCalculator.Stream.Write(derEncoded, 0, derEncoded.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
popoSigningKeyInput = new PopoSigningKeyInput(_publicKeyMAC, _pubKeyInfo);
|
||||
byte[] derEncoded = popoSigningKeyInput.GetDerEncoded();
|
||||
streamCalculator.Stream.Write(derEncoded, 0, derEncoded.Length);
|
||||
}
|
||||
streamCalculator.Stream.Flush();
|
||||
streamCalculator.Stream.Close();
|
||||
DefaultSignatureResult defaultSignatureResult = (DefaultSignatureResult)streamCalculator.GetResult();
|
||||
return new PopoSigningKey(popoSigningKeyInput, (AlgorithmIdentifier)signer.AlgorithmDetails, new DerBitString(defaultSignatureResult.Collect()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Crmf;
|
||||
|
||||
namespace Org.BouncyCastle.Crmf;
|
||||
|
||||
public class RegTokenControl : IControl
|
||||
{
|
||||
private static readonly DerObjectIdentifier type = CrmfObjectIdentifiers.id_regCtrl_regToken;
|
||||
|
||||
private readonly DerUtf8String token;
|
||||
|
||||
public DerObjectIdentifier Type => type;
|
||||
|
||||
public Asn1Encodable Value => token;
|
||||
|
||||
public RegTokenControl(DerUtf8String token)
|
||||
{
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public RegTokenControl(string token)
|
||||
{
|
||||
this.token = new DerUtf8String(token);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user