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/jdk1.1/org/spongycastle/cert/crmf')
-rw-r--r--pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/CertificateRequestMessage.java309
-rw-r--r--pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/FixedLengthMGF1Padder.java120
-rw-r--r--pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java134
-rw-r--r--pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java485
-rw-r--r--pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java120
-rw-r--r--pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java140
-rw-r--r--pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java69
7 files changed, 1377 insertions, 0 deletions
diff --git a/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/CertificateRequestMessage.java b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/CertificateRequestMessage.java
new file mode 100644
index 00000000..6f582812
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/CertificateRequestMessage.java
@@ -0,0 +1,309 @@
+package org.spongycastle.cert.crmf;
+
+import java.io.IOException;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERUTF8String;
+import org.spongycastle.asn1.crmf.AttributeTypeAndValue;
+import org.spongycastle.asn1.crmf.CRMFObjectIdentifiers;
+import org.spongycastle.asn1.crmf.CertReqMsg;
+import org.spongycastle.asn1.crmf.CertTemplate;
+import org.spongycastle.asn1.crmf.Controls;
+import org.spongycastle.asn1.crmf.PKIArchiveOptions;
+import org.spongycastle.asn1.crmf.PKMACValue;
+import org.spongycastle.asn1.crmf.POPOSigningKey;
+import org.spongycastle.asn1.crmf.ProofOfPossession;
+import org.spongycastle.cert.CertIOException;
+import org.spongycastle.operator.ContentVerifier;
+import org.spongycastle.operator.ContentVerifierProvider;
+import org.spongycastle.operator.OperatorCreationException;
+
+/**
+ * Carrier for a CRMF CertReqMsg.
+ */
+public class CertificateRequestMessage
+{
+ public static final int popRaVerified = ProofOfPossession.TYPE_RA_VERIFIED;
+ public static final int popSigningKey = ProofOfPossession.TYPE_SIGNING_KEY;
+ public static final int popKeyEncipherment = ProofOfPossession.TYPE_KEY_ENCIPHERMENT;
+ public static final int popKeyAgreement = ProofOfPossession.TYPE_KEY_AGREEMENT;
+
+ private CertReqMsg certReqMsg;
+ private Controls controls;
+
+ private static CertReqMsg parseBytes(byte[] encoding)
+ throws IOException
+ {
+ try
+ {
+ return CertReqMsg.getInstance(ASN1Primitive.fromByteArray(encoding));
+ }
+ catch (ClassCastException e)
+ {
+ throw new CertIOException("malformed data: " + e.getMessage(), e);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CertIOException("malformed data: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Create a CertificateRequestMessage from the passed in bytes.
+ *
+ * @param certReqMsg BER/DER encoding of the CertReqMsg structure.
+ * @throws IOException in the event of corrupted data, or an incorrect structure.
+ */
+ public CertificateRequestMessage(byte[] certReqMsg)
+ throws IOException
+ {
+ this(parseBytes(certReqMsg));
+ }
+
+ public CertificateRequestMessage(CertReqMsg certReqMsg)
+ {
+ this.certReqMsg = certReqMsg;
+ this.controls = certReqMsg.getCertReq().getControls();
+ }
+
+ /**
+ * Return the underlying ASN.1 object defining this CertificateRequestMessage object.
+ *
+ * @return a CertReqMsg.
+ */
+ public CertReqMsg toASN1Structure()
+ {
+ return certReqMsg;
+ }
+
+ /**
+ * Return the certificate template contained in this message.
+ *
+ * @return a CertTemplate structure.
+ */
+ public CertTemplate getCertTemplate()
+ {
+ return this.certReqMsg.getCertReq().getCertTemplate();
+ }
+
+ /**
+ * Return whether or not this request has control values associated with it.
+ *
+ * @return true if there are control values present, false otherwise.
+ */
+ public boolean hasControls()
+ {
+ return controls != null;
+ }
+
+ /**
+ * Return whether or not this request has a specific type of control value.
+ *
+ * @param type the type OID for the control value we are checking for.
+ * @return true if a control value of type is present, false otherwise.
+ */
+ public boolean hasControl(ASN1ObjectIdentifier type)
+ {
+ return findControl(type) != null;
+ }
+
+ /**
+ * Return a control value of the specified type.
+ *
+ * @param type the type OID for the control value we are checking for.
+ * @return the control value if present, null otherwise.
+ */
+ public Control getControl(ASN1ObjectIdentifier type)
+ {
+ AttributeTypeAndValue found = findControl(type);
+
+ if (found != null)
+ {
+ if (found.getType().equals(CRMFObjectIdentifiers.id_regCtrl_pkiArchiveOptions))
+ {
+ return new PKIArchiveControl(PKIArchiveOptions.getInstance(found.getValue()));
+ }
+ if (found.getType().equals(CRMFObjectIdentifiers.id_regCtrl_regToken))
+ {
+ return new RegTokenControl(DERUTF8String.getInstance(found.getValue()));
+ }
+ if (found.getType().equals(CRMFObjectIdentifiers.id_regCtrl_authenticator))
+ {
+ return new AuthenticatorControl(DERUTF8String.getInstance(found.getValue()));
+ }
+ }
+
+ return null;
+ }
+
+ private AttributeTypeAndValue findControl(ASN1ObjectIdentifier type)
+ {
+ if (controls == null)
+ {
+ return null;
+ }
+
+ AttributeTypeAndValue[] tAndVs = controls.toAttributeTypeAndValueArray();
+ AttributeTypeAndValue found = null;
+
+ for (int i = 0; i != tAndVs.length; i++)
+ {
+ if (tAndVs[i].getType().equals(type))
+ {
+ found = tAndVs[i];
+ break;
+ }
+ }
+
+ return found;
+ }
+
+ /**
+ * Return whether or not this request message has a proof-of-possession field in it.
+ *
+ * @return true if proof-of-possession is present, false otherwise.
+ */
+ public boolean hasProofOfPossession()
+ {
+ return this.certReqMsg.getPopo() != null;
+ }
+
+ /**
+ * Return the type of the proof-of-possession this request message provides.
+ *
+ * @return one of: popRaVerified, popSigningKey, popKeyEncipherment, popKeyAgreement
+ */
+ public int getProofOfPossessionType()
+ {
+ return this.certReqMsg.getPopo().getType();
+ }
+
+ /**
+ * Return whether or not the proof-of-possession (POP) is of the type popSigningKey and
+ * it has a public key MAC associated with it.
+ *
+ * @return true if POP is popSigningKey and a PKMAC is present, false otherwise.
+ */
+ public boolean hasSigningKeyProofOfPossessionWithPKMAC()
+ {
+ ProofOfPossession pop = certReqMsg.getPopo();
+
+ if (pop.getType() == popSigningKey)
+ {
+ POPOSigningKey popoSign = POPOSigningKey.getInstance(pop.getObject());
+
+ return popoSign.getPoposkInput().getPublicKeyMAC() != null;
+ }
+
+ return false;
+ }
+
+ /**
+ * Return whether or not a signing key proof-of-possession (POP) is valid.
+ *
+ * @param verifierProvider a provider that can produce content verifiers for the signature contained in this POP.
+ * @return true if the POP is valid, false otherwise.
+ * @throws CRMFException if there is a problem in verification or content verifier creation.
+ * @throws IllegalStateException if POP not appropriate.
+ */
+ public boolean isValidSigningKeyPOP(ContentVerifierProvider verifierProvider)
+ throws CRMFException, IllegalStateException
+ {
+ ProofOfPossession pop = certReqMsg.getPopo();
+
+ if (pop.getType() == popSigningKey)
+ {
+ POPOSigningKey popoSign = POPOSigningKey.getInstance(pop.getObject());
+
+ if (popoSign.getPoposkInput() != null && popoSign.getPoposkInput().getPublicKeyMAC() != null)
+ {
+ throw new IllegalStateException("verification requires password check");
+ }
+
+ return verifySignature(verifierProvider, popoSign);
+ }
+ else
+ {
+ throw new IllegalStateException("not Signing Key type of proof of possession");
+ }
+ }
+
+ /**
+ * Return whether or not a signing key proof-of-possession (POP), with an associated PKMAC, is valid.
+ *
+ * @param verifierProvider a provider that can produce content verifiers for the signature contained in this POP.
+ * @param macBuilder a suitable PKMACBuilder to create the MAC verifier.
+ * @param password the password used to key the MAC calculation.
+ * @return true if the POP is valid, false otherwise.
+ * @throws CRMFException if there is a problem in verification or content verifier creation.
+ * @throws IllegalStateException if POP not appropriate.
+ */
+ public boolean isValidSigningKeyPOP(ContentVerifierProvider verifierProvider, PKMACBuilder macBuilder, char[] password)
+ throws CRMFException, IllegalStateException
+ {
+ ProofOfPossession pop = certReqMsg.getPopo();
+
+ if (pop.getType() == popSigningKey)
+ {
+ POPOSigningKey popoSign = POPOSigningKey.getInstance(pop.getObject());
+
+ if (popoSign.getPoposkInput() == null || popoSign.getPoposkInput().getSender() != null)
+ {
+ throw new IllegalStateException("no PKMAC present in proof of possession");
+ }
+
+ PKMACValue pkMAC = popoSign.getPoposkInput().getPublicKeyMAC();
+ PKMACValueVerifier macVerifier = new PKMACValueVerifier(macBuilder);
+
+ if (macVerifier.isValid(pkMAC, password, this.getCertTemplate().getPublicKey()))
+ {
+ return verifySignature(verifierProvider, popoSign);
+ }
+
+ return false;
+ }
+ else
+ {
+ throw new IllegalStateException("not Signing Key type of proof of possession");
+ }
+ }
+
+ private boolean verifySignature(ContentVerifierProvider verifierProvider, POPOSigningKey popoSign)
+ throws CRMFException
+ {
+ ContentVerifier verifier;
+
+ try
+ {
+ verifier = verifierProvider.get(popoSign.getAlgorithmIdentifier());
+ }
+ catch (OperatorCreationException e)
+ {
+ throw new CRMFException("unable to create verifier: " + e.getMessage(), e);
+ }
+
+ if (popoSign.getPoposkInput() != null)
+ {
+ CRMFUtil.derEncodeToStream(popoSign.getPoposkInput(), verifier.getOutputStream());
+ }
+ else
+ {
+ CRMFUtil.derEncodeToStream(certReqMsg.getCertReq(), verifier.getOutputStream());
+ }
+
+ return verifier.verify(popoSign.getSignature().getBytes());
+ }
+
+ /**
+ * Return the ASN.1 encoding of the certReqMsg we wrap.
+ *
+ * @return a byte array containing the binary encoding of the certReqMsg.
+ * @throws IOException if there is an exception creating the encoding.
+ */
+ public byte[] getEncoded()
+ throws IOException
+ {
+ return certReqMsg.getEncoded();
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/FixedLengthMGF1Padder.java b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/FixedLengthMGF1Padder.java
new file mode 100644
index 00000000..cfb33d62
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/FixedLengthMGF1Padder.java
@@ -0,0 +1,120 @@
+package org.spongycastle.cert.crmf;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.generators.MGF1BytesGenerator;
+import org.spongycastle.crypto.params.MGFParameters;
+
+/**
+ * An encrypted value padder that uses MGF1 as the basis of the padding.
+ */
+public class FixedLengthMGF1Padder
+ implements EncryptedValuePadder
+{
+ private int length;
+ private SecureRandom random;
+ private Digest dig = new SHA1Digest();
+
+ /**
+ * Create a padder to so that padded output will always be at least
+ * length bytes long.
+ *
+ * @param length fixed length for padded output.
+ */
+ public FixedLengthMGF1Padder(int length)
+ {
+ this(length, null);
+ }
+
+ /**
+ * Create a padder to so that padded output will always be at least
+ * length bytes long, using the passed in source of randomness to
+ * provide the random material for the padder.
+ *
+ * @param length fixed length for padded output.
+ * @param random a source of randomness.
+ */
+ public FixedLengthMGF1Padder(int length, SecureRandom random)
+ {
+ this.length = length;
+ this.random = random;
+ }
+
+ public byte[] getPaddedData(byte[] data)
+ {
+ byte[] bytes = new byte[length];
+ byte[] seed = new byte[dig.getDigestSize()];
+ byte[] mask = new byte[length - dig.getDigestSize()];
+
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ random.nextBytes(seed);
+
+ MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig);
+
+ maskGen.init(new MGFParameters(seed));
+
+ maskGen.generateBytes(mask, 0, mask.length);
+
+ System.arraycopy(seed, 0, bytes, 0, seed.length);
+ System.arraycopy(data, 0, bytes, seed.length, data.length);
+
+ for (int i = seed.length + data.length + 1; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)(1 + Math.abs(random.nextInt()) % 254);
+ }
+
+ for (int i = 0; i != mask.length; i++)
+ {
+ bytes[i + seed.length] ^= mask[i];
+ }
+
+ return bytes;
+ }
+
+ public byte[] getUnpaddedData(byte[] paddedData)
+ {
+ byte[] seed = new byte[dig.getDigestSize()];
+ byte[] mask = new byte[length - dig.getDigestSize()];
+
+ System.arraycopy(paddedData, 0, seed, 0, seed.length);
+
+ MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig);
+
+ maskGen.init(new MGFParameters(seed));
+
+ maskGen.generateBytes(mask, 0, mask.length);
+
+ for (int i = 0; i != mask.length; i++)
+ {
+ paddedData[i + seed.length] ^= mask[i];
+ }
+
+ int end = 0;
+
+ for (int i = paddedData.length - 1; i != seed.length; i--)
+ {
+ if (paddedData[i] == 0)
+ {
+ end = i;
+ break;
+ }
+ }
+
+ if (end == 0)
+ {
+ throw new IllegalStateException("bad padding in encoding");
+ }
+
+ byte[] data = new byte[end - seed.length];
+
+ System.arraycopy(paddedData, seed.length, data, 0, data.length);
+
+ return data;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java
new file mode 100644
index 00000000..eec071e1
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/bc/BcFixedLengthMGF1Padder.java
@@ -0,0 +1,134 @@
+package org.spongycastle.cert.crmf.bc;
+
+import java.security.SecureRandom;
+
+import org.spongycastle.cert.crmf.EncryptedValuePadder;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.generators.MGF1BytesGenerator;
+import org.spongycastle.crypto.params.MGFParameters;
+
+/**
+ * An encrypted value padder that uses MGF1 as the basis of the padding.
+ */
+public class BcFixedLengthMGF1Padder
+ implements EncryptedValuePadder
+{
+ private int length;
+ private SecureRandom random;
+ private Digest dig = new SHA1Digest();
+
+ /**
+ * Create a padder to so that padded output will always be at least
+ * length bytes long.
+ *
+ * @param length fixed length for padded output.
+ */
+ public BcFixedLengthMGF1Padder(int length)
+ {
+ this(length, null);
+ }
+
+ /**
+ * Create a padder to so that padded output will always be at least
+ * length bytes long, using the passed in source of randomness to
+ * provide the random material for the padder.
+ *
+ * @param length fixed length for padded output.
+ * @param random a source of randomness.
+ */
+ public BcFixedLengthMGF1Padder(int length, SecureRandom random)
+ {
+ this.length = length;
+ this.random = random;
+ }
+
+ public byte[] getPaddedData(byte[] data)
+ {
+ byte[] bytes = new byte[length];
+ byte[] seed = new byte[dig.getDigestSize()];
+ byte[] mask = new byte[length - dig.getDigestSize()];
+
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ random.nextBytes(seed);
+
+ MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig);
+
+ maskGen.init(new MGFParameters(seed));
+
+ maskGen.generateBytes(mask, 0, mask.length);
+
+ System.arraycopy(seed, 0, bytes, 0, seed.length);
+ System.arraycopy(data, 0, bytes, seed.length, data.length);
+
+ for (int i = seed.length + data.length + 1; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)(1 + nextByte(random));
+ }
+
+ for (int i = 0; i != mask.length; i++)
+ {
+ bytes[i + seed.length] ^= mask[i];
+ }
+
+ return bytes;
+ }
+
+ public byte[] getUnpaddedData(byte[] paddedData)
+ {
+ byte[] seed = new byte[dig.getDigestSize()];
+ byte[] mask = new byte[length - dig.getDigestSize()];
+
+ System.arraycopy(paddedData, 0, seed, 0, seed.length);
+
+ MGF1BytesGenerator maskGen = new MGF1BytesGenerator(dig);
+
+ maskGen.init(new MGFParameters(seed));
+
+ maskGen.generateBytes(mask, 0, mask.length);
+
+ for (int i = 0; i != mask.length; i++)
+ {
+ paddedData[i + seed.length] ^= mask[i];
+ }
+
+ int end = 0;
+
+ for (int i = paddedData.length - 1; i != seed.length; i--)
+ {
+ if (paddedData[i] == 0)
+ {
+ end = i;
+ break;
+ }
+ }
+
+ if (end == 0)
+ {
+ throw new IllegalStateException("bad padding in encoding");
+ }
+
+ byte[] data = new byte[end - seed.length];
+
+ System.arraycopy(paddedData, seed.length, data, 0, data.length);
+
+ return data;
+ }
+
+ private int nextByte(SecureRandom random)
+ {
+ int bits, val;
+ do
+ {
+ bits = random.nextInt() & 0x7fffffff;
+ val = bits % 255;
+ }
+ while (bits - val + 254 < 0);
+
+ return val;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java
new file mode 100644
index 00000000..afed7590
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/CRMFHelper.java
@@ -0,0 +1,485 @@
+package org.spongycastle.cert.crmf.jcajce;
+
+import java.io.IOException;
+import java.security.AlgorithmParameterGenerator;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.RC2ParameterSpec;
+
+import org.spongycastle.asn1.ASN1Encodable;
+import org.spongycastle.asn1.ASN1Null;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERBitString;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.iana.IANAObjectIdentifiers;
+import org.spongycastle.asn1.nist.NISTObjectIdentifiers;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.asn1.x9.X9ObjectIdentifiers;
+import org.spongycastle.cert.crmf.CRMFException;
+import org.spongycastle.cms.CMSAlgorithm;
+import org.spongycastle.cms.CMSEnvelopedDataGenerator;
+import org.spongycastle.jcajce.util.JcaJceHelper;
+
+class CRMFHelper
+{
+ protected static final Map BASE_CIPHER_NAMES = new HashMap();
+ protected static final Map CIPHER_ALG_NAMES = new HashMap();
+ protected static final Map DIGEST_ALG_NAMES = new HashMap();
+ protected static final Map KEY_ALG_NAMES = new HashMap();
+ protected static final Map MAC_ALG_NAMES = new HashMap();
+
+ static
+ {
+ BASE_CIPHER_NAMES.put(PKCSObjectIdentifiers.des_EDE3_CBC, "DESEDE");
+ BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes128_CBC, "AES");
+ BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes192_CBC, "AES");
+ BASE_CIPHER_NAMES.put(NISTObjectIdentifiers.id_aes256_CBC, "AES");
+
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDE/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.AES256_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(new ASN1ObjectIdentifier(PKCSObjectIdentifiers.rsaEncryption.getId()), "RSA/ECB/PKCS1Padding");
+
+ DIGEST_ALG_NAMES.put(OIWObjectIdentifiers.idSHA1, "SHA1");
+ DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha224, "SHA224");
+ DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha256, "SHA256");
+ DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha384, "SHA384");
+ DIGEST_ALG_NAMES.put(NISTObjectIdentifiers.id_sha512, "SHA512");
+
+ MAC_ALG_NAMES.put(IANAObjectIdentifiers.hmacSHA1, "HMACSHA1");
+ MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA1, "HMACSHA1");
+ MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA224, "HMACSHA224");
+ MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA256, "HMACSHA256");
+ MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA384, "HMACSHA384");
+ MAC_ALG_NAMES.put(PKCSObjectIdentifiers.id_hmacWithSHA512, "HMACSHA512");
+
+ KEY_ALG_NAMES.put(PKCSObjectIdentifiers.rsaEncryption, "RSA");
+ KEY_ALG_NAMES.put(X9ObjectIdentifiers.id_dsa, "DSA");
+ }
+
+ private JcaJceHelper helper;
+
+ CRMFHelper(JcaJceHelper helper)
+ {
+ this.helper = helper;
+ }
+
+ PublicKey toPublicKey(SubjectPublicKeyInfo subjectPublicKeyInfo)
+ throws CRMFException
+ {
+
+ try
+ {
+ X509EncodedKeySpec xspec = new X509EncodedKeySpec(new DERBitString(subjectPublicKeyInfo).getBytes());
+ AlgorithmIdentifier keyAlg = subjectPublicKeyInfo.getAlgorithmId();
+ return createKeyFactory(keyAlg.getAlgorithm()).generatePublic(xspec);
+ }
+ catch (IOException e)
+ {
+ throw new CRMFException("invalid key: " + e.getMessage(), e);
+ }
+ catch (InvalidKeySpecException e)
+ {
+ throw new CRMFException("invalid key: " + e.getMessage(), e);
+ }
+ }
+
+ Cipher createCipher(ASN1ObjectIdentifier algorithm)
+ throws CRMFException
+ {
+ try
+ {
+ String cipherName = (String)CIPHER_ALG_NAMES.get(algorithm);
+
+ if (cipherName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createCipher(cipherName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createCipher(algorithm.getId());
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
+ }
+ }
+
+ public KeyGenerator createKeyGenerator(ASN1ObjectIdentifier algorithm)
+ throws CRMFException
+ {
+ try
+ {
+ String cipherName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (cipherName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createKeyGenerator(cipherName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createKeyGenerator(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CRMFException("cannot create key generator: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CRMFException("cannot create key generator: " + e.getMessage(), e);
+ }
+ }
+
+ Cipher createContentCipher(final Key sKey, final AlgorithmIdentifier encryptionAlgID)
+ throws CRMFException
+ {
+ return (Cipher)execute(new JCECallback()
+ {
+ public Object doInJCE()
+ throws CRMFException, InvalidAlgorithmParameterException,
+ InvalidKeyException, InvalidParameterSpecException, NoSuchAlgorithmException,
+ NoSuchPaddingException, NoSuchProviderException
+ {
+ Cipher cipher = createCipher(encryptionAlgID.getAlgorithm());
+ ASN1Primitive sParams = (ASN1Primitive)encryptionAlgID.getParameters();
+ String encAlg = encryptionAlgID.getAlgorithm().getId();
+
+ if (sParams != null && !(sParams instanceof ASN1Null))
+ {
+ try
+ {
+ AlgorithmParameters params = createAlgorithmParameters(encryptionAlgID.getAlgorithm());
+
+ try
+ {
+ params.init(sParams.getEncoded(), "ASN.1");
+ }
+ catch (IOException e)
+ {
+ throw new CRMFException("error decoding algorithm parameters.", e);
+ }
+
+ cipher.init(Cipher.DECRYPT_MODE, sKey, params);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.AES128_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.AES192_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.AES256_CBC))
+ {
+ cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec(
+ ASN1OctetString.getInstance(sParams).getOctets()));
+ }
+ else
+ {
+ throw e;
+ }
+ }
+ }
+ else
+ {
+ if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.CAST5_CBC))
+ {
+ cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec(new byte[8]));
+ }
+ else
+ {
+ cipher.init(Cipher.DECRYPT_MODE, sKey);
+ }
+ }
+
+ return cipher;
+ }
+ });
+ }
+
+ AlgorithmParameters createAlgorithmParameters(ASN1ObjectIdentifier algorithm)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (algorithmName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createAlgorithmParameters(algorithmName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createAlgorithmParameters(algorithm.getId());
+ }
+
+ KeyFactory createKeyFactory(ASN1ObjectIdentifier algorithm)
+ throws CRMFException
+ {
+ try
+ {
+ String algName = (String)KEY_ALG_NAMES.get(algorithm);
+
+ if (algName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createKeyFactory(algName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createKeyFactory(algorithm.getId());
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
+ }
+ }
+
+ MessageDigest createDigest(ASN1ObjectIdentifier algorithm)
+ throws CRMFException
+ {
+ try
+ {
+ String digestName = (String)DIGEST_ALG_NAMES.get(algorithm);
+
+ if (digestName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createDigest(digestName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createDigest(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CRMFException("cannot create cipher: " + e.getMessage(), e);
+ }
+ }
+
+ Mac createMac(ASN1ObjectIdentifier algorithm)
+ throws CRMFException
+ {
+ try
+ {
+ String macName = (String)MAC_ALG_NAMES.get(algorithm);
+
+ if (macName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createMac(macName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createMac(algorithm.getId());
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CRMFException("cannot create mac: " + e.getMessage(), e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CRMFException("cannot create mac: " + e.getMessage(), e);
+ }
+ }
+
+ AlgorithmParameterGenerator createAlgorithmParameterGenerator(ASN1ObjectIdentifier algorithm)
+ throws GeneralSecurityException
+ {
+ String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ try
+ {
+ if (algorithmName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createAlgorithmParameterGenerator(algorithmName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createAlgorithmParameterGenerator(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new GeneralSecurityException(e.toString());
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new GeneralSecurityException(e.toString());
+ }
+ }
+
+ AlgorithmParameters generateParameters(ASN1ObjectIdentifier encryptionOID, SecretKey encKey, SecureRandom rand)
+ throws CRMFException
+ {
+ try
+ {
+ AlgorithmParameterGenerator pGen = createAlgorithmParameterGenerator(encryptionOID);
+
+ if (encryptionOID.equals(CMSEnvelopedDataGenerator.RC2_CBC))
+ {
+ byte[] iv = new byte[8];
+
+ rand.nextBytes(iv);
+
+ try
+ {
+ pGen.init(new RC2ParameterSpec(encKey.getEncoded().length * 8, iv), rand);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new CRMFException("parameters generation error: " + e, e);
+ }
+ }
+
+ return pGen.generateParameters();
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CRMFException("exception creating algorithm parameter generator: " + e, e);
+ }
+ }
+
+ AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier encryptionOID, AlgorithmParameters params)
+ throws CRMFException
+ {
+ ASN1Encodable asn1Params;
+ if (params != null)
+ {
+ try
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ }
+ catch (IOException e)
+ {
+ throw new CRMFException("cannot encode parameters: " + e.getMessage(), e);
+ }
+ }
+ else
+ {
+ asn1Params = DERNull.INSTANCE;
+ }
+
+ return new AlgorithmIdentifier(
+ encryptionOID,
+ asn1Params);
+ }
+
+ static Object execute(JCECallback callback) throws CRMFException
+ {
+ try
+ {
+ return callback.doInJCE();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CRMFException("can't find algorithm.", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CRMFException("key invalid in message.", e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CRMFException("can't find provider.", e);
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new CRMFException("required padding not supported.", e);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new CRMFException("algorithm parameters invalid.", e);
+ }
+ catch (InvalidParameterSpecException e)
+ {
+ throw new CRMFException("MAC algorithm parameter spec invalid.", e);
+ }
+ }
+
+ static interface JCECallback
+ {
+ Object doInJCE()
+ throws CRMFException, InvalidAlgorithmParameterException, InvalidKeyException, InvalidParameterSpecException,
+ NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java
new file mode 100644
index 00000000..0cf87509
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceAsymmetricValueDecryptorGenerator.java
@@ -0,0 +1,120 @@
+package org.spongycastle.cert.crmf.jcajce;
+
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.ProviderException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.cert.crmf.CRMFException;
+import org.spongycastle.cert.crmf.ValueDecryptorGenerator;
+import org.spongycastle.jcajce.util.DefaultJcaJceHelper;
+import org.spongycastle.jcajce.util.NamedJcaJceHelper;
+import org.spongycastle.jcajce.util.ProviderJcaJceHelper;
+import org.spongycastle.operator.InputDecryptor;
+
+public class JceAsymmetricValueDecryptorGenerator
+ implements ValueDecryptorGenerator
+{
+ private PrivateKey recipientKey;
+ private CRMFHelper helper = new CRMFHelper(new DefaultJcaJceHelper());
+
+ public JceAsymmetricValueDecryptorGenerator(PrivateKey recipientKey)
+ {
+ this.recipientKey = recipientKey;
+ }
+
+ public JceAsymmetricValueDecryptorGenerator setProvider(Provider provider)
+ {
+ this.helper = new CRMFHelper(new ProviderJcaJceHelper(provider));
+
+ return this;
+ }
+
+ public JceAsymmetricValueDecryptorGenerator setProvider(String providerName)
+ {
+ this.helper = new CRMFHelper(new NamedJcaJceHelper(providerName));
+
+ return this;
+ }
+
+ private Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey)
+ throws CRMFException
+ {
+ try
+ {
+ Key sKey = null;
+
+ Cipher keyCipher = helper.createCipher(keyEncryptionAlgorithm.getAlgorithm());
+
+ try
+ {
+ keyCipher.init(Cipher.UNWRAP_MODE, recipientKey);
+ sKey = keyCipher.unwrap(encryptedContentEncryptionKey, contentEncryptionAlgorithm.getAlgorithm().getId(), Cipher.SECRET_KEY);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ }
+ catch (IllegalStateException e)
+ {
+ }
+ catch (UnsupportedOperationException e)
+ {
+ }
+ catch (ProviderException e)
+ {
+ }
+
+ // some providers do not support UNWRAP (this appears to be only for asymmetric algorithms)
+ if (sKey == null)
+ {
+ keyCipher.init(Cipher.DECRYPT_MODE, recipientKey);
+ sKey = new SecretKeySpec(keyCipher.doFinal(encryptedContentEncryptionKey), contentEncryptionAlgorithm.getAlgorithm().getId());
+ }
+
+ return sKey;
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CRMFException("key invalid in message.", e);
+ }
+ catch (IllegalBlockSizeException e)
+ {
+ throw new CRMFException("illegal blocksize in message.", e);
+ }
+ catch (BadPaddingException e)
+ {
+ throw new CRMFException("bad padding in message.", e);
+ }
+ }
+
+ public InputDecryptor getValueDecryptor(AlgorithmIdentifier keyEncryptionAlgorithm, final AlgorithmIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey)
+ throws CRMFException
+ {
+ Key secretKey = extractSecretKey(keyEncryptionAlgorithm, contentEncryptionAlgorithm, encryptedContentEncryptionKey);
+
+ final Cipher dataCipher = helper.createContentCipher(secretKey, contentEncryptionAlgorithm);
+
+ return new InputDecryptor()
+ {
+ public AlgorithmIdentifier getAlgorithmIdentifier()
+ {
+ return contentEncryptionAlgorithm;
+ }
+
+ public InputStream getInputStream(InputStream dataIn)
+ {
+ return new CipherInputStream(dataIn, dataCipher);
+ }
+ };
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java
new file mode 100644
index 00000000..5be72f2a
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JceCRMFEncryptorBuilder.java
@@ -0,0 +1,140 @@
+package org.spongycastle.cert.crmf.jcajce;
+
+import java.io.OutputStream;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.InvalidKeyException;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.cert.crmf.CRMFException;
+import org.spongycastle.jcajce.util.DefaultJcaJceHelper;
+import org.spongycastle.jcajce.util.NamedJcaJceHelper;
+import org.spongycastle.jcajce.util.ProviderJcaJceHelper;
+import org.spongycastle.operator.GenericKey;
+import org.spongycastle.operator.OutputEncryptor;
+
+public class JceCRMFEncryptorBuilder
+{
+ private ASN1ObjectIdentifier encryptionOID;
+ private int keySize;
+
+ private CRMFHelper helper = new CRMFHelper(new DefaultJcaJceHelper());
+ private SecureRandom random;
+
+ public JceCRMFEncryptorBuilder(ASN1ObjectIdentifier encryptionOID)
+ {
+ this(encryptionOID, -1);
+ }
+
+ public JceCRMFEncryptorBuilder(ASN1ObjectIdentifier encryptionOID, int keySize)
+ {
+ this.encryptionOID = encryptionOID;
+ this.keySize = keySize;
+ }
+
+ public JceCRMFEncryptorBuilder setProvider(Provider provider)
+ {
+ this.helper = new CRMFHelper(new ProviderJcaJceHelper(provider));
+
+ return this;
+ }
+
+ public JceCRMFEncryptorBuilder setProvider(String providerName)
+ {
+ this.helper = new CRMFHelper(new NamedJcaJceHelper(providerName));
+
+ return this;
+ }
+
+ public JceCRMFEncryptorBuilder setSecureRandom(SecureRandom random)
+ {
+ this.random = random;
+
+ return this;
+ }
+
+ public OutputEncryptor build()
+ throws CRMFException
+ {
+ return new CRMFOutputEncryptor(encryptionOID, keySize, random);
+ }
+
+ private class CRMFOutputEncryptor
+ implements OutputEncryptor
+ {
+ private SecretKey encKey;
+ private AlgorithmIdentifier algorithmIdentifier;
+ private Cipher cipher;
+
+ CRMFOutputEncryptor(ASN1ObjectIdentifier encryptionOID, int keySize, SecureRandom random)
+ throws CRMFException
+ {
+ KeyGenerator keyGen = helper.createKeyGenerator(encryptionOID);
+
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ if (keySize < 0)
+ {
+ keyGen.init(random);
+ }
+ else
+ {
+ keyGen.init(keySize, random);
+ }
+
+ cipher = helper.createCipher(encryptionOID);
+ encKey = keyGen.generateKey();
+ AlgorithmParameters params = helper.generateParameters(encryptionOID, encKey, random);
+
+ try
+ {
+ cipher.init(Cipher.ENCRYPT_MODE, encKey, params, random);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CRMFException("unable to initialize cipher: " + e.getMessage(), e);
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CRMFException("unable to initialize cipher: " + e.getMessage(), e);
+ }
+
+ //
+ // If params are null we try and second guess on them as some providers don't provide
+ // algorithm parameter generation explicity but instead generate them under the hood.
+ //
+ if (params == null)
+ {
+ params = cipher.getParameters();
+ }
+
+ algorithmIdentifier = helper.getAlgorithmIdentifier(encryptionOID, params);
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier()
+ {
+ return algorithmIdentifier;
+ }
+
+ public OutputStream getOutputStream(OutputStream dOut)
+ {
+ return new CipherOutputStream(dOut, cipher);
+ }
+
+ public GenericKey getKey()
+ {
+ return new GenericKey(encKey);
+ }
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java
new file mode 100644
index 00000000..6c593709
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/spongycastle/cert/crmf/jcajce/JcePKMACValuesCalculator.java
@@ -0,0 +1,69 @@
+package org.spongycastle.cert.crmf.jcajce;
+
+import java.security.MessageDigest;
+import java.security.Provider;
+import java.security.InvalidKeyException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.cert.crmf.CRMFException;
+import org.spongycastle.cert.crmf.PKMACValuesCalculator;
+import org.spongycastle.jcajce.util.DefaultJcaJceHelper;
+import org.spongycastle.jcajce.util.NamedJcaJceHelper;
+import org.spongycastle.jcajce.util.ProviderJcaJceHelper;
+
+public class JcePKMACValuesCalculator
+ implements PKMACValuesCalculator
+{
+ private MessageDigest digest;
+ private Mac mac;
+ private CRMFHelper helper;
+
+ public JcePKMACValuesCalculator()
+ {
+ this.helper = new CRMFHelper(new DefaultJcaJceHelper());
+ }
+
+ public JcePKMACValuesCalculator setProvider(Provider provider)
+ {
+ this.helper = new CRMFHelper(new ProviderJcaJceHelper(provider));
+
+ return this;
+ }
+
+ public JcePKMACValuesCalculator setProvider(String providerName)
+ {
+ this.helper = new CRMFHelper(new NamedJcaJceHelper(providerName));
+
+ return this;
+ }
+
+ public void setup(AlgorithmIdentifier digAlg, AlgorithmIdentifier macAlg)
+ throws CRMFException
+ {
+ digest = helper.createDigest(digAlg.getAlgorithm());
+ mac = helper.createMac(macAlg.getAlgorithm());
+ }
+
+ public byte[] calculateDigest(byte[] data)
+ {
+ return digest.digest(data);
+ }
+
+ public byte[] calculateMac(byte[] pwd, byte[] data)
+ throws CRMFException
+ {
+ try
+ {
+ mac.init(new SecretKeySpec(pwd, mac.getAlgorithm()));
+
+ return mac.doFinal(data);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CRMFException("failure in setup: " + e.getMessage(), e);
+ }
+ }
+}