Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pkix/src/main/java/org/spongycastle/cert/cmp/ProtectedPKIMessage.java')
-rw-r--r--pkix/src/main/java/org/spongycastle/cert/cmp/ProtectedPKIMessage.java198
1 files changed, 198 insertions, 0 deletions
diff --git a/pkix/src/main/java/org/spongycastle/cert/cmp/ProtectedPKIMessage.java b/pkix/src/main/java/org/spongycastle/cert/cmp/ProtectedPKIMessage.java
new file mode 100644
index 00000000..b5dbb980
--- /dev/null
+++ b/pkix/src/main/java/org/spongycastle/cert/cmp/ProtectedPKIMessage.java
@@ -0,0 +1,198 @@
+package org.spongycastle.cert.cmp;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.spongycastle.asn1.ASN1EncodableVector;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.DERSequence;
+import org.spongycastle.asn1.cmp.CMPCertificate;
+import org.spongycastle.asn1.cmp.CMPObjectIdentifiers;
+import org.spongycastle.asn1.cmp.PBMParameter;
+import org.spongycastle.asn1.cmp.PKIBody;
+import org.spongycastle.asn1.cmp.PKIHeader;
+import org.spongycastle.asn1.cmp.PKIMessage;
+import org.spongycastle.cert.X509CertificateHolder;
+import org.spongycastle.cert.crmf.PKMACBuilder;
+import org.spongycastle.operator.ContentVerifier;
+import org.spongycastle.operator.ContentVerifierProvider;
+import org.spongycastle.operator.MacCalculator;
+import org.spongycastle.util.Arrays;
+
+/**
+ * Wrapper for a PKIMessage with protection attached to it.
+ */
+public class ProtectedPKIMessage
+{
+ private PKIMessage pkiMessage;
+
+ /**
+ * Base constructor.
+ *
+ * @param pkiMessage a GeneralPKIMessage with
+ */
+ public ProtectedPKIMessage(GeneralPKIMessage pkiMessage)
+ {
+ if (!pkiMessage.hasProtection())
+ {
+ throw new IllegalArgumentException("PKIMessage not protected");
+ }
+
+ this.pkiMessage = pkiMessage.toASN1Structure();
+ }
+
+ ProtectedPKIMessage(PKIMessage pkiMessage)
+ {
+ if (pkiMessage.getHeader().getProtectionAlg() == null)
+ {
+ throw new IllegalArgumentException("PKIMessage not protected");
+ }
+
+ this.pkiMessage = pkiMessage;
+ }
+
+ /**
+ * Return the message header.
+ *
+ * @return the message's PKIHeader structure.
+ */
+ public PKIHeader getHeader()
+ {
+ return pkiMessage.getHeader();
+ }
+
+ /**
+ * Return the message body.
+ *
+ * @return the message's PKIBody structure.
+ */
+ public PKIBody getBody()
+ {
+ return pkiMessage.getBody();
+ }
+
+ /**
+ * Return the underlying ASN.1 structure contained in this object.
+ *
+ * @return a PKIMessage structure.
+ */
+ public PKIMessage toASN1Structure()
+ {
+ return pkiMessage;
+ }
+
+ /**
+ * Determine whether the message is protected by a password based MAC. Use verify(PKMACBuilder, char[])
+ * to verify the message if this method returns true.
+ *
+ * @return true if protection MAC PBE based, false otherwise.
+ */
+ public boolean hasPasswordBasedMacProtection()
+ {
+ return pkiMessage.getHeader().getProtectionAlg().getAlgorithm().equals(CMPObjectIdentifiers.passwordBasedMac);
+ }
+
+ /**
+ * Return the extra certificates associated with this message.
+ *
+ * @return an array of extra certificates, zero length if none present.
+ */
+ public X509CertificateHolder[] getCertificates()
+ {
+ CMPCertificate[] certs = pkiMessage.getExtraCerts();
+
+ if (certs == null)
+ {
+ return new X509CertificateHolder[0];
+ }
+
+ X509CertificateHolder[] res = new X509CertificateHolder[certs.length];
+ for (int i = 0; i != certs.length; i++)
+ {
+ res[i] = new X509CertificateHolder(certs[i].getX509v3PKCert());
+ }
+
+ return res;
+ }
+
+ /**
+ * Verify a message with a public key based signature attached.
+ *
+ * @param verifierProvider a provider of signature verifiers.
+ * @return true if the provider is able to create a verifier that validates
+ * the signature, false otherwise.
+ * @throws CMPException if an exception is thrown trying to verify the signature.
+ */
+ public boolean verify(ContentVerifierProvider verifierProvider)
+ throws CMPException
+ {
+ ContentVerifier verifier;
+ try
+ {
+ verifier = verifierProvider.get(pkiMessage.getHeader().getProtectionAlg());
+
+ return verifySignature(pkiMessage.getProtection().getBytes(), verifier);
+ }
+ catch (Exception e)
+ {
+ throw new CMPException("unable to verify signature: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Verify a message with password based MAC protection.
+ *
+ * @param pkMacBuilder MAC builder that can be used to construct the appropriate MacCalculator
+ * @param password the MAC password
+ * @return true if the passed in password and MAC builder verify the message, false otherwise.
+ * @throws CMPException if algorithm not MAC based, or an exception is thrown verifying the MAC.
+ */
+ public boolean verify(PKMACBuilder pkMacBuilder, char[] password)
+ throws CMPException
+ {
+ if (!CMPObjectIdentifiers.passwordBasedMac.equals(pkiMessage.getHeader().getProtectionAlg().getAlgorithm()))
+ {
+ throw new CMPException("protection algorithm not mac based");
+ }
+
+ try
+ {
+ pkMacBuilder.setParameters(PBMParameter.getInstance(pkiMessage.getHeader().getProtectionAlg().getParameters()));
+ MacCalculator calculator = pkMacBuilder.build(password);
+
+ OutputStream macOut = calculator.getOutputStream();
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pkiMessage.getHeader());
+ v.add(pkiMessage.getBody());
+
+ macOut.write(new DERSequence(v).getEncoded(ASN1Encoding.DER));
+
+ macOut.close();
+
+ return Arrays.areEqual(calculator.getMac(), pkiMessage.getProtection().getBytes());
+ }
+ catch (Exception e)
+ {
+ throw new CMPException("unable to verify MAC: " + e.getMessage(), e);
+ }
+ }
+
+ private boolean verifySignature(byte[] signature, ContentVerifier verifier)
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pkiMessage.getHeader());
+ v.add(pkiMessage.getBody());
+
+ OutputStream sOut = verifier.getOutputStream();
+
+ sOut.write(new DERSequence(v).getEncoded(ASN1Encoding.DER));
+
+ sOut.close();
+
+ return verifier.verify(signature);
+ }
+}