Protocol Standards Compliance:
Application Extensible Design:
Proven Interoperability:
Cryptographic Provider Independence:
CMS is the IETF standardized successor of the PKCS7v1.5 protocol developed by RSA Inc.. It specifies several cryptographic mechanisms for digitally signing, digesting, authenticating or encrypting any kind of data. As main difference to PKCS#7, CMS takes care of algorithm independence and introduces additional content formats and processing rules.
S/MIMEv4, S/MIMEv3 are the IETF standardized successors of the S/MIMEv2 protocol developed by RSA Inc. It uses the cryptographic mechanisms specified by CMS for securing MIME formatted messages. As S/MIMEv2 already has been some kind of industry standard for secure email transfer over the internet, S/MIMEv4 and S/MIMEv3 adopt the amendments of CMS for becoming an internet standard. Today any notable email client like Mozilla Thunderbird or Microsoft Outlook is able to speak S/MIME.
ESS enhances the S/MIME protocol about some additional security services that are based on the Secure Data Network System (SDNS) Message Security Protocol of the NSA, but maybe useful in many other environments, particularly business and finance applications, too.
As CMS succeeds PKCS#7v1.5 and S/MIMEv4 succeeds S/MIMEv2 and S/MIMEv3, IAIK-CMS with S/MIMEv4 is the successor library of the PKCS#7 implementation of IAIK-JCE and the S/MIMEv2 implementation of IAIK-SMIME. IAIK-CMS operates on top of the IAIK-JCE API, which is included in the license. As for IAIK-JCE, we provide Applet and WebStart Editions for IAIK-CMS, too.
IAIK-JCE contains an implementation of the PKCS#7 standard, and IAIK-SMIME was an implementation of the S/MIMEv2 protocol. IAIK-CMS with S/MIMEv4 implements the CMS (Cryptographic Message Syntax), S/MIMEv4 and ESS (Enhanced Security Services for S/MIME) protocols. Since CMS is the successor of PKCS#7 and S/MIMEv4, S/MIMEv3 are the successors of S/MIMEv2, IAIK-CMS with S/MIMEv4 succeeds both, the PKCS#7 library of IAIK-JCE and the IAIK-SMIME library.
The API of IAIK-CMS maintains the design of IAIK-JCE and IAIK-SMIME, so that is can be used in a similar way. However, package names have been changed and enhancments/modifications have been made where required to fulfill the CMS and S/MIMEv3 protocols. The, for instance, signature contributing attributes of a PKCS#7 SignedData type are named as “authenticated attributes”, whereas CMS refers to them as “signed attributes”. In similar way, PKCS#7 calculates an “encrypted digest” value (since it only uses the RSA algorithm), but CMS calculates a “signature value”. Thus the names of the corresponding SignedData(Stream) methods have been changed from
set/getAuthenticatedAttributes to set/getSignedAttributes, and the names of the corresponding SignerInfo methods set/getEncryptedDigest have been changed to set/getSignatureValue.
As another example, PKCS#7 only used one (RSA based) RecipientInfo type for encrypting the temporary symmetric content encryption key of an EnvelopedData message. In addition to this “KeyTransRecipientInfo” type (where the content encryption key is encrypted with the public key of the recipient), CMS introduces the RecipientInfo alternatives “KeyAgreeRecipientInfo”, “KEKRecipientInfo”, “PasswordRecipientInfo”, and “OtherRecipientInfo”. To group all these types, the one and only class RecipientInfo of IAIK-JCE has become an interface in IAIK-CMS allowing to use all different RecipientInfo types in a common way.
In order to ugrade from IAIK-JCE and/or IAIK-SMIME to IAIK-CMS the most straightforward way might be to change all package names from iaik.pkcs and
iaik.pkcs.pkcs7 to iaik.cms., and all package names from iaik.security.smime to
iaik.smime and then run the compiler to find and change all class and method names as required.
IAIK-CMS contains a so-called SecurityProvider utility that centralizes all cryptographic code into one class. It can be implemented by an application to plug-in its own cryptogarphic service implementations. The PKCS#7 library contains a limited SecurityProvider version: The
RSACipherProvider allows an application to use its own RSA cipher implementation for digest value en/decryption or content key en/decryption for SignerInfo or RecipientInfo objects, respectively. An application that uses this RSACipherProvider may replace it by a corresponding CMS SecurityProvider implementation by overriding any of the signature creation/verification or key encryption/decryption methods as required (see the IAIK-CMS Javadoc for more information).
Because the package name of the S/MIME library has changed from iaik.security.smime to iaik.smime, it is also necessary to update the IAIK mailcap entries accordingly (see the Installation Notes contained in the IAIK-CMS distribution):
The relevant mailcap-file entries should look like
#
# IAIK 'mailcap' file
#
multipart/signed;; x-java-content-handler=iaik.smime.signed_content
application/x-pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content
application/x-pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content
application/pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content
application/pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content
application/x-pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content
application/pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content
To, for instance, use a RSA PKCS#1v1.5 compliant smartcard for signature calculatuion only, you may extend the IAIK-CMS IaikProvider and override method calculateSignatureFromSignedAttributes, e.g.:
public class MySecurityProvider extends IaikProvider {
...
public byte[] calculateSignatureFromSignedAttributes(
AlgorithmID signatureAlgorithm,
AlgorithmID digestAlgorithm,
PrivateKey privateKey,
byte[] signedAttributes)
throws NoSuchAlgorithmException,
InvalidKeyException,
SignatureException {
byte[] signatureValue = null;
// get the implementation name: RSA?
String implementationName =
signatureAlgorithm.getImplementationName();
if (implementationName == IMPLEMENTATION_NAME_RSA) {
// let the smartcard calculate the signature value
byte[] signatureValue = …;
} else {
signatureValue =
super.calculateSignatureFromSignedAttributes(
signatureAlgorithm,
digestAlgorithm,
privateKey,
signedAttributes);
}
return signatureValue;
}
}
Now tell the IAIK-CMS libary to use your SecurityProvider implementation:
MySecurityProvider mySecurityProvider = ...;
SecurityProvider.setSecurityProvider(mySecurityProvider);
Note that you also may install a SecurityProvider per CMS object. See our
SecurityProvider description and the IAIK-CMS Javadoc for more detailed information.
If the smartcard or HSM your are using supports the PKCS#11 standard, you may use ourPKCS#11 provider to access it from your Java™ application.
IAIK-CMS adopts the SecurityProvider model introduced by the IAIK-TLS library (iSaSiLk) for centralizing all cryptographic tasks into one class,
iaik.cms.SecurityProvider.The SecurityProvider model used here is similar to that of iSaSiLk except for a the following changes:
Class iaik.cms.SecurityProvider is the main class of the IAIK-CMS SecurityProvider model. It itself provides default implementations for most of the cryptographic operations required by CMS, expect for functionalities that are not available from JCA/JCE engines by default, like, for instance, Ephemeral Static Diffie Hellman. Unfortunately there is no general way to initialize a
KeyPairGenerator with algorithm parameters as required when creating a originator ESDH key pair with domain parameters matching to those of the recipient´s public key. So the default implementation of method generateKeyAgreementKeyPair(AlgorithmID keyAgreeAlgorithm, PublicKey otherKey) has to throw an exception and has to be mplemented if using another cryptographic provider than IAIK. The same applies to method createSharedKeyEncryptionKey which cannot handle an ESDHKeyAgreement in provider independent way. So at the current state it might be preferable to override all ESDH related methods when intending to use another provider than IAIK.
With class IaikProvider IAIK-CMS contains an SecurityProvider implemention for the IAIK cryptography provider of the crypto toolkit IAIK-JCE. Please note the difference: The IAIK provider is a JCA/JCE cryptography provider supplying cryptographic engines; Class IaikProvider is an IAIK-CMS SecurityProvider implementation that makes the cryptographic engines of the IAIK JCA/JCE cyrptography provider available for IAIK-CMS. Per default IAIK-CMS is configured to look if the IAIK cryptography provider is available. If yes, it uses the IaikProvider as SecurityProvider. If not it uses the default SecurityProvider implementation. Thus if you want to use the IAIK provider you do not have to take any care about the SecurityProvider setting. However, if you do not want to use the IAIK provider for some reasons (e.g. you require a specific, e.g. smartcard depending, handling for some tasks) you have two options:
Use the default SecurityProvider implementation by setting it as SecurityProvider to be used
SecurityProvider.setSecurityProvider(new SecurityProvider());
Implement your own SecurityProvider for the required cryptographic tasks and install it as SecurityProvider to be used:
MySecurityProvider mySecurityProvider = ...;
SecurityProvider.setSecurityProvider(mySecurityProvider);
If choosing the second option from above basically you may follow one of two ways for implementing your own SecurityProvider:
In the first case you may extend the IaikProvider class, e.g.:
public class MySecurityProvider extends IaikProvider {
...
public byte[] calculateSignatureFromSignedAttributes(
AlgorithmID signatureAlgorithm,
AlgorithmID digestAlgorithm,
PrivateKey privateKey,
byte[] signedAttributes)
throws NoSuchAlgorithmException,
InvalidKeyException,
SignatureException {
byte[] signatureValue = null;
// get the implementation name: RSA?
String implementationName =
signatureAlgorithm.getImplementationName();
if (implementationName == IMPLEMENTATION_NAME_RSA) {
// let the smartcard calculate the signature value
byte[] signatureValue = ...;
} else {
signatureValue =
super.calculateSignatureFromSignedAttributes(
signatureAlgorithm,
digestAlgorithm,
privateKey,
signedAttributes);
}
return signatureValue;
}
}
If the smartcard or HSM your are using supports the PKCS#11 standard, you may use our PKCS#11 provider to access it from your Java™ application.
In the second case, if you want to use a different provider alltogether and not use the IAIK-JCE at all (for whatever reason 😉 you may start with the SecurityProvider class and override those methods where you cannot use the default implementation.
Note that you also may install a SecurityProvider per CMS object. To, for instance, use one specific SecurityProvider only for one specific
SignedDataStream object, you may use its setSecurityProvider method, e.g.:
MySecurityProvider myProvider = ...;
SignedDataStream signedData = ...;
signedData.setSecurityProvider(myProvider);
Now myProvider will be used for any cryptographic operation required by this one specific SignedDataStream object. If any of the CMS objects (SignerInfos) belonging to this SignedDataStream object needs a SecurityProvider, it will use myProvider, too; except for those, who already have installed their own SecurityProvider. However, SecurityProviders are only forwarded from “higher” to “lower” objects, e.g.: if a SignedData(Stream) object has its own SecurityProvider it forwards it to its SignerInfos objects (as long as they do not already have their own SecurityProviders), but if a SignerInfo with its own SecurityProvider is added to a SignedData(Stream) object that has no SecurityProvider installed, the SecurityProvider of the SignerInfo is not forwarded to the SignedData(Stream) object. In this case the SignedDataStream object will use the default, system-wide installed SecurityProvider (which should be available in any case).
If you want to use a specific SecurityProvider for a specific CMS object please look at the Javadoc™ if you may add it by using method
setSecurityProvider (if present), or if you already may install it via the constructor (which may required when, for instance, parsing a CMS object that needs cryptographic engines already during the parsing procedure (e.g. for digest calculation initialization when parsing a SignedData object)).
Online: Javadoc for IAIK-CMS
Class or Package | Bug / Change / New Feature | Description and Examples |
---|---|---|
iaik.cms.AuthEnvelopedData, iaik.cms.AuthEnvelopedDataStream, iaik.cms.AuthEnvelopedDataOutputStream | NF | Support for ChaCha20-Poly1305 Authenticated Encryption according to RFC 8419 added. |
iaik.cms.AuthEnvelopedData, iaik.cms.AuthEnvelopedDataStream, iaik.cms.AuthEnvelopedDataOutputStream | NF | Support for Elliptic Curve Diffie-Hellman Key Agreement Algorithm KeyAgreeRecipientInfo with X25519 and X448 according to RFC 8418 added. |
iaik.cms.AuthEnvelopedData, iaik.cms.AuthEnvelopedDataStream | NF | Support for explicit mode. |
iaik.cms.AuthEnvelopedData, iaik.cms.AuthEnvelopedDataStream | NF | Support for explicit mode. |
iaik.cms.AuthEnvelopedDataStream | NF | Support for AES-CBC-CMAC. |
iaik.cms.AuthEnvelopedDataStream | NF | Support for stream based parsing. |
iaik.cms.AuthenticateddData, iaik.cms.AuthenticatedDataStream, iaik.cms.AuthenticatedOutputStream | NF | Support for Elliptic Curve Diffie-Hellman Key Agreement Algorithm KeyAgreeRecipientInfo with X25519 and X448 according to RFC 8418 added. |
iaik.cms.CanonicalizeOutputStream | B | Fixed zero data handling in writeTo(). |
iaik.cms.ContentInfoStream | C | toASN1Object: use blockSize of underlying type to decide between definite and indefinite encoding. |
iaik.cms.EncryptedContentInfo | B | toASN1Object(): fixed explicit/implicit content encoding |
iaik.cms.EncryptedContentInfoStream | B | Fixed EXPLICIT/IMPLICIT reference in setMode() |
iaik.cms.EncryptedData, iaik.cms.EncryptedDataStream | C | Increased iteration count. |
iaik.cms.EnvelopedData, iaik.cms.EnvelopedDataStream, iaik.cms.EnvelopedDataOutputStream | NF | Support for Elliptic Curve Diffie-Hellman Key Agreement Algorithm KeyAgreeRecipientInfo with X25519 and X448 according to RFC 8418 added. |
iaik.cms.EnvelopedData, iaik.cms.EnvelopedDataStream | NF | AEAD support added. |
iaik.cms.EnvelopedDataStream | B | Fixed calculateVersion() |
iaik.cms.IaikProvider, iaik.cms.SecurityProvider | NF, C | Now allow to use IAIK-CMS also without the necessity to install the JCA Provider within the JCA Security framework. |
iaik.cms.KeyAgreeRecipientInfo | C | Generates ukm automatically if not supplied. |
iaik.cms.SignedData, iaik.cms.SignedDataStream, iaik.cms.SignedDataOutputStream | NF | Support for Edwards-Curve Digital Signature Algorithm (EdDSA; Ed25519, Ed448) according RFC 8103. |
iaik.cms.RecipientEncryptedKey | C | decryptKey(): check also for NULL params, encryptKey(): set keyAgreeAlg only if not included yet |
iaik.cms.ecc.ECCelerateProvider | C | The CMS SecurityProvider for the Elliptic Curve Library IAIK-ECCelerateECCelerateTM is now included into iaik_cms.jar. Therefore iaik_eccelerate_cms.jar is no more required and has to be removed from the classpath! |
iaik.cms.ecc.ECCelerateProvider | NF, C | Aligned with IAIK-CMS 6.0 to support S/MIMEv4. |
iaik.cms.ecc.ECCelerateProvider | C | Fixed AES, DESEde key wrap AlgorithmID parameter field encoding (aligned with RFC 3278 successor RFC 5753). |
iaik.cms.ecc.ECCelerateProvider | NF | Support added for key agreement schemes dhSinglePass-stdDH-sha224kdf-scheme, dhSinglePass-stdDH-sha512kdf-scheme, dhSinglePass-cofactorDH-sha224kdf-scheme, dhSinglePass-cofactorDH-sha256kdf-scheme, dhSinglePass-cofactorDH-sha384kdf-scheme, dhSinglePass-cofactorDH-sha512kdf-scheme added. |
iaik.cms.Utils | NF | Added methods createPssAlgorithmID(), createOaepAlgorithmID(). |
iaik.smime.* | NF | Support for S/MIME v4 (RFC 8551). |
iaik.smime.AuthEncryptedContent, iaik.smime.SMimeAuthEncrypted | NF | Support for S/MIME (v4) authenticated encryption according to RFC 8551. |
iaik.smime.encrypted_content | NF | application/pkcs7-mime DataContentHandler for authenveloped-data added. |
iaik.smime.ess.utils.KeyStoreDatabase | NF, C | Support for certificate identifiers of type SubjectKeyID and RecipientKeyIdentifier added. |
iaik.smime.ess.utils.EncryptedKeyStoreDatabase | NF | KeyDatabase implementation that keeps the key entries in the base KeyStore and does not decrypt them before actually using them. |
demo.smime.DumpMessage | NF, C | Uses the KeyStoreDatabase utility to maintain recipient keys/certifcates by their certificate identifier. |
demo.smime.basic.SMimeOaepPssDemo | NF | New demo showing the use for RSA-PSS and RSA-OAEP for signing and enveloping S/MIME messages. |
Class or Package | Bug / Change / New Feature | Description and Examples |
---|---|---|
iaik.cms.AuthenticatedData, iaik.cms.AuthenticatedDataStream, iaik.cms.AuthenticatedDataOutputStream, iaik.cms.SignedData, iaik.cms.SignedDataStream, iaik.cms.SignedDataOutputStream, iaik.cms.SignerInfo, iaik.cms.attributes.CounterSignature | C | Changed ContentType attribute handling. When creating a SignedData* or AuthenticatedData* object the ContentType attribute is automatically added if not included in the provided signed/authenticated attributes. During verification now an InvalidContentTypeException is also thrown if signed attributes are present but do not contain the ContentType attribute. When creating/verifying a CounterSignature attribute a ContentType attribute must not be included. |
iaik.cms.CertificateChoices | NF | Class CertificateChoices to provide explicit access to the |
iaik.cms.CertificateSet | NF | Methods add/get/setCertificateChoices added. |
iaik.cms.CMSAlgorithmID | NF | Constructor added to parse AlgorithmID from a DerInputStream. |
iaik.cms.CMSAlgorithmID | C | aes128_CBC, aes128_CCM, aes128_GCM: |
iaik.cms.CMSAttribute | NF | Extends class iaik.asn1.structures.Attribute to can keep the encoding when parsing an attribute from an InputStream (when SignedDataInOutStream is used). |
iaik.cms.attributes.CMSContentType, iaik.cms.attributes.CMSMessageDigest, iaik.cms.attributes.SigningTime | C | Now override method multipleAllowed to return false |
iaik.cms.EncodedAttributeValue | NF | New class that represents a CMS AttributeValue together with its BER encoded representation. Maybe got from an CMSAttribute object after parsing to get the parsed encoded |
iaik.cms.EnvelopedDataStream, iaik.cms.EnvelopedData, iaik.cms.EncryptedContentInfoStream, iaik.cms.EncryptedContentInfo | NF | Support for explicit mode where the encrypted content maybe transmitted by other means outside the EnvelopedData/EncryptedContentInfo. |
iaik.cms.ecc.IaikEccProvider | NF | Support for BSI TR-03109 (“ECKA-EG”) added. Note, however, that the usage of the old IAIK-ECC library is deprecated. For ECC the new IAIK ECCelerate(TM) |
iaik.cms.OCSPRevocationInfo | NF | Implements the CMS type OtherRevocationInfoFormat for the OtherRevocationInfo format OCSP (id-ri-ocsp-response – 1.3.6.1.5.5.7.16.2) according to RFC 5940. |
iaik.cms.RevocationInfoChoice | NF | Class RevocationInfoChoice to provide explicit access to the |
iaik.cms.RevocationInfoChoices | NF | Methods for adding/setting/counting/querying general RevocationInfoChoice and OCSPRevocationInfo objects added. |
iaik.cms.SecurityProvider | B, C | getInputStreamCipherEngine(), getByteArrayCipherEngine(), getInputStreamAuthCipherEngine(), getByteArrayAuthCipherEngine(), getAuthCipherEngine(): set SecurityProvider for the returned engines. |
iaik.cms.SecurityProvider | B | Fixed reflection signature based parameter setting. |
iaik.cms.SignedAttributes | NF | Implements the signed attributes set of a CMS SignerInfo. |
iaik.cms.SignerIdentifier | NF | Implements the SignerIdentifier type of CMS SignerInfo. It is defined as ASN.1 CHOICE of IssuerAndSerialNumber or SubjectKeyIdentifier. |
iaik.cms.SignatureValue | NF | Provides an alternative way to get the signature value from a SignerInfo object obtained from a SignedDataInOutStream object during parsing to get the encoded representation of the signature value. |
iaik.cms.SignerInfo | NF | Constructor and decode method added to parse AlgorithmID from a DerInputStream. |
iaik.cms.SignerInfo | C | toASN1Object() keeps the sorting of the parsed signed attributes when encoding a SignerInfo again |
iaik.cms.SignerInfo | C | Added method removeUnsignedAttribute; declared methods addUnSignedAttribute, removeUnSignedAttribute |
iaik.cms.SignedDataStream | C | SignerInfo(s) are now parsed using DerInputStream. |
iaik.cms.SignedDataStream | NF | Method addDigestAlgorithm added. |
iaik.cms.SignedDataStream | NF | Method addSDSEncodeListener added to allow usage of more than one EncodeListener |
iaik.cms.SignedDataInOutStream | NF | SignedDataStream implementation that encodes a SignedData object again during parsing is done. The SignedData object may be modified before finishing the encoding. |
iaik.smime.attributes.SMIMECapabilities, iaik.smime.attributes.SMIMEEncryptionKeyPreference | C | Now override method multipleAllowed to return false |
iaik.smime.ess.ContentHints, iaik.smime.ess.ContentIdentifier, iaik.smime.ess.ESSSecurityLabel, iaik.smime.ess.MsgSigDigest, iaik.smime.ess.MLExpansionHistory, iaik.smime.ess.ReceiptRequest, iaik.smime.ess.ContentReference, iaik.smime.ess.EquivalentLabels, iaik.smime.ess.SigningCertificate | C | Now override method multipleAllowed to return false |
Occasionally verification of RSA based signatures seem to fail when using IAIK-CMS 4.0.The problem does not occur with IAIK-CMS 5.0
Some signature applications seem to use different parameter encoding practices (NULL or absent parameter) for digestAlgorithm(s) fields and DigestInfo encoding during signature calculation for one and the same SignedData/SignerInfo. IAIK-CMS 4.0 uses an raw RSA Signature engine for signature verification and assumes the same parameter encoding for digestAlgorithm(s) field and DigestInfo encoding. With IAIK-CMS 4.0 the problem can be fixed by using, e.g. an Cipher based SecurityProvider like the IaikCCProvider:
SecurityProvider.setSecurityProvider(new IaikCCProvider());
IAIK-CMS 5.0 fixes this problem by using a special raw Signature engine checking both encoding practices.
Although usually SignedData objects or signed S/MIME messages containing a SigningCertificateV2 attribute can be verified without problems, sometimes verification fails when the included SignerInfo contains a SigningCertificateV2 attribute.The problem occurs only with IAIk-CMS versions prior 5.0
There are some application(s) which erroneously encode the SigningCertificateV2 attribute by including the hashAlgorithm field of the ESSCertIDv2 component even if the default hash algorithm (SHA-256) is used. Since default components have to be omitted the encoding is different and signature verification will fail. The current version of IAIK-CMS (5.0) fixes this problem by keeping the encoding when parsing a SigningCertificateV2 attribute. With versions prior 5.0 you may write and register a SigningCertificateV2 attribute implementation that keeps the encoding.
When running the ProcessMessageDemo with JavaMail™ 1.5 I get an exception saying that there is no MimeMessage/MimeBodyPart content. With JavaMail™ 1.4 all works fine!
The ProcessMessageDemo takes an existing (received) message and signs/encrypts it anew. Due to a bug in JavaMail™ 1.5 the Content-Type and Content-Transfer-Encoding headers may not be properly updated when copying the DataHandler from an existing to a new message. The bug will be fixed in the next version of JavaMail™. The next version of IAIK-CMS (5.0) will contain a workaround to solve this problem for JavaMail™ 1.5.
My S/MIME appliaction does not work properly with JavaMail™ version 1.3.3. Signatures cannot be verified and encrypted messages cannot be decrypted. However, all works well with JavaMail™ 1.3.2.
There seems to be a bug in the BASE64 decoding routine used by JavaMail™ version 1.3.3. For that reason base64 encoded MIME parts cannot be properly decoded and you may get exception messages like the one described in the following bug report. Unfortunetaly we cannot provide a workaround for this problem since base64 decoding is invoked inside the JavaMail™ library. You may use a JavaMail™ version prior 1.3.3 (e.g. 1.3.2) or you may switch to JavaMail™ 1.4 which already has fixed the problem. However, please note that JavaMail™ 1.4 only can be used with JDK 1.4 or later.
When using JavaMail™ 1.3.3 and running the SMimeDemo I get the following exception saying that the signature cannot be verifie
java.security.SignatureException: Signature verification error: iaik.cms.CMSSignatureException: SignerInfo does not exist. Wrong index.
at demo.smime.DumpMessage.dump(DumpMessage.java:118)
at demo.smime.SMimeV3Demo.start(SMimeDemo.java:213)
at demo.smime.SMimeV3Demo.main(SMimeDemo.java:882)
java.lang.RuntimeException
at demo.smime.SMimeV3Demo.start(SMimeDemo.java:465)
at demo.smime.SMimeV3Demo.main(SMimeDemo.java:882)
A: Due to a bug in the BASE64 decoding routine used by JavaMail™ version 1.3.3 the SignedData object cannot be decoded corretly. For that reason it is not possible to verify the signature. Unfortunetaly we cannot provide a workaround for this problem since base64 decoding is invoked inside the JavaMail™ library. You may a JavaMail™ version prior 1.3.3 (e.g. 1.3.2) or you may switch to JavaMail™ 1.4 which already has fixed the problem. However, please note that JavaMail™ 1.4 only can be used with JDK 1.4 or later.
I have used the S/MIME library of IAIK-CMS to create and sign a multipart/mixed MIME entity consisting of only one body part:
Content-Type: multipart/mixed;
boundary="----=_Part_0_1551868.1088869295069"
——=_Part_0_1551868.1088869295069
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hello world !
——=_Part_0_1551868.1088869295069–
Athough I have no problems to display the message and verify the signature when using Mozilla, both Outlook Express and Outlook are not able to handle the message.
For some reason Outlook Express and Outlook seem to have problems with multipart/signed messages where the content consists of a multipart/mixed MIME entity that contains only one body part. However, when creating an implicit signed message (application/pkcs7-mime), Outlook and Outlook Express are able to handle the message, too. So you may either create an application/pkcs7-mime message:
boolean implicit = true;
SignedContent sc = new SignedContent(implicit);
or not to use a multipart/mixed entity that only consists of one body part with an explicit SignedContent object (multipart/signed). For your sample you may immediately call method setText of class SignedContent:
boolean implicit = false;
SignedContent sc = new SignedContent(false);
sc.setText(“Hello world !”);
I have used the S/MIME library of IAIK-CMS to create and send a triple wrapped (signed-encrypted-signed) message to an Outlook Express mail client. Outlook express is able to resolve and display the message, but complains that the signature is not correct. For the signed parts I have used the “multipart/signed” content type (explicit SignedContent).
For some reason some versions of Outlook Express seem to have problems when verifying the signatures of nested multipart/signed messages. You may use the application/pkcs7-mime (signed-data) content type by creating implicit SignedContent objects.
I have used the S/MIME library of IAIK-CMS to create and send a signed message to an Outlook Express mail client. I have included my encryption certificate into the SignedData message, but Outlook Express is not able to fetch it from the certificates field. I am using different certificates for signing and encryption.
Some versions of Outlook Express and Outlook 98 are not able to recognize the encryption certificate included in a signed message when separate certificates are used for signing/encryption. Some versions of MS Outlook Express even complain that the contents maybe altered. The reason for this strange behaviour is that MS uses a private attribute (OID “1.3.6.1.4.1.311.16.4”) for identifying the encryption certificate of the sender by issuer name and serial number. When adding signer information to your SignedContent object you will have to ensure to use a proper addSigner method that creates and adds the required private MS attribute to the corresponding SignerInfo object (see Javadoc™ of class SignedContent for choosing the right addSigner method). It might be noticed that S/MIMEv3 introduced new attribute (SMIMEEncryptionKeyPreference) allowing to include identification information similar to the Microsoft attribute. You may allow method addSigner to set this attribute, too.
When trying the SMimeSend demo, an exception is thrown saying that there is no data content handler for the S/MIME content types.
The mapping between S/MIME types and data content handlers is done by a RFC1524 mailcap file which is included in the IAIK-S/MIME distribution (named “mailcap”) to be copied into the lib directory of your Java™Home (e.g. C:/Java/j2re1.4.2/lib). You alternatively may register the IAIK-S/MIME mailcap file dynamically by using the default command map:
String mailcapFileName = …;
MailcapCommandMap mc = new MailcapCommandMap(mailcapFileName);
CommandMap.setDefaultCommandMap(mc);
Or you may add the IAIK mailcap entries to the default mailcap command map, e.g.:
MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap();
mc.addMailcap(“multipart/signed;; x-java-content-handler=iaik.smime.signed_content”);
mc.addMailcap(“application/x-pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content”);
mc.addMailcap(“application/x-pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content”);
mc.addMailcap(“application/pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content”);
mc.addMailcap(“application/pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content”);
mc.addMailcap(“application/x-pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content”);
mc.addMailcap(“application/pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content”);
CommandMap.setDefaultCommandMap(mc);
For a more detailed description of mailcap handling consult the Javadoc™ of the Activation Framework.
When using the S/MIME library, I get a ClassCastException to iaik.asn1.structures. Name from the Java™ JarVerifier:
java.lang.ClassCastException: iaik.asn1.structures.Name
at sun.security.pkcs.PKCS7.getCertificate(PKCS7.java:569)
at sun.security.pkcs.SignerInfo.getCertificate(SignerInfo.java:198)
at sun.security.pkcs.SignerInfo.verify(SignerInfo.java:324)
at sun.security.pkcs.PKCS7.verify(PKCS7.java:463)
at sun.security.pkcs.PKCS7.verify(PKCS7.java:480)
at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:143)
at java.util.jar.JarVerifier.processEntry(JarVerifier.java:279)
I am using JDK1.3 and have the IAIK-JCE crypto provider (jar file is not signed) installed as first provider.
Some versions of the JavaMail™ jar files (e.g. mail.jar) and the Java™ Activation Framework jar files (activation.jar) may be signed. Due to a bug (hardcoded cast to SUN´s distinguished name implementation) in the jar file verification mechanism of some JDK versions it may be necessary to have SUN based DSA/RSA capable providers installed before the IAIK provider when the jar file verification takes places. However, you still may use IAIK as first provider if you take care to load classes from the mail.jar and activation.jar files before installing the IAIK provider. For instance, you may register the mailcap file and create a Session object, e.g.:
// register content data handlers for S/MIME types
MailcapCommandMap mc = new MailcapCommandMap(“mailcap”);
CommandMap.setDefaultCommandMap(mc);
// create some properties and get the default Session
Properties props = new Properties();
props.put(“mail.smtp.host”, host);
Session session = Session.getDefaultInstance(props, null);
// now install IAIK as first provider
IAIK.addAsProvider();
Now MailcapCommandMap and Session are loaded from activation.jar and mail.jar, respectively, and the signatures of these two jar files are verified before the IAIK provider is installed.
When installing the IAIK-JCE provider (signed version) as first provider for IAIK-CMS and trying to do some cipher operation (e.g. with the EnvelopedData type) a stack overflow error occurs. I am using JDK 1.4.
Due to a bug in the JDK jar file verification mechanism it may be necessary that the original SUN provider is installed as first provider. So insert the IAIK provider as second provider and explicitly request an IAIK engine when calling getInstance:
Security.insertProviderAt(new IAIK(), 2);
Cipher c = Cipher.getInstance(“DES/CBC/PKCS5Padding”, “IAIK”);
Alternatively you may use static method addAsJDK14Provider of the IAIK-JCE provider main class. This method uses a work around that allows to use IAIK as first provider for JDK1.4, too:
IAIK.addAsJDK14Provider();
When using IAIK-JCE as crypto provider for IAIK-CMS and trying to do some cipher operation (e.g. with the EnvelopedData type) I get an ExceptionInInitializerError is thrown saying “Cannot set up certs for trusted CAs”. I am using JDK 1.4.
With JDK1.4 the JCE framework (JAVAX CRYPTO) has been incorporated into the standard JDK. Because of export regulations a JCE provider only maybe used with JDK1.4 (or JCE 1.2.1) if it is signed. IAIK-JCE provides signed and unsigned versions of its jar files (iaik_jce.jar, iaik_jce_full.jar). Using the unsigned version with JDK 1.4 will cause the ExceptionInInitializerError “Cannot set up certs for trusted CAs”. Please use the signed jar file.
You also may ensure that the right JCE policy files are installed in the lib/security directory. due to import control restrictions of some countries, JDK1.4 per default comes with jurisdiction policy files allowing “strong” but limited cryptography; so keys that exeed the allowed strength are not allowed to be used by this policy. If you are entitled to do so, you may download and install an “unlimited strengh” version of these files. Usually, you can download them from the same web page as the Java™ runtime or JDK. Usually these files have to be put into the lib/security subdirectory of your JRE; however some VMs (e.g. IBM) may require to put them into another directory (e.g. lib/ext). Please read the installation instructions that come with these policy files. Take care to install these policy files in the correct JRE installation. Note that many JDKs install two JREs by default and that the one which is used by default is not(!) the one embedded in the JDK directory. To see which one is used, you may type java™ -verbose -version.
Occasionally verification of RSA based signatures seem to fail when using IAIK-CMS 4.0.The problem does not occur with IAIK-CMS 5.0
Some signature applications seem to use different parameter encoding practices (NULL or absent parameter) for digestAlgorithm(s) fields and DigestInfo encoding during signature calculation for one and the same SignedData/SignerInfo. IAIK-CMS 4.0 uses an raw RSA Signature engine for signature verification and assumes the same parameter encoding for digestAlgorithm(s) field and DigestInfo encoding. With IAIK-CMS 4.0 the problem can be fixed by using, e.g. an Cipher based SecurityProvider like the IaikCCProvider:
SecurityProvider.setSecurityProvider(new IaikCCProvider());
IAIK-CMS 5.0 fixes this problem by using a special raw Signature engine checking both encoding practices.
Although usually SignedData objects or signed S/MIME messages containing a SigningCertificateV2 attribute can be verified without problems, sometimes verification fails when the included SignerInfo contains a SigningCertificateV2 attribute.The problem occurs only with IAIk-CMS versions prior 5.0
There are some application(s) which erroneously encode the SigningCertificateV2 attribute by including the hashAlgorithm field of the ESSCertIDv2 component even if the default hash algorithm (SHA-256) is used. Since default components have to be omitted the encoding is different and signature verification will fail. The current version of IAIK-CMS (5.0) fixes this problem by keeping the encoding when parsing a SigningCertificateV2 attribute. With versions prior 5.0 you may write and register a SigningCertificateV2 attribute implementation that keeps the encoding.
When running the ProcessMessageDemo with JavaMail™ 1.5 I get an exception saying that there is no MimeMessage/MimeBodyPart content. With JavaMail™ 1.4 all works fine!
The ProcessMessageDemo takes an existing (received) message and signs/encrypts it anew. Due to a bug in JavaMail™ 1.5 the Content-Type and Content-Transfer-Encoding headers may not be properly updated when copying the DataHandler from an existing to a new message. The bug will be fixed in the next version of JavaMail™. The next version of IAIK-CMS (5.0) will contain a workaround to solve this problem for JavaMail™ 1.5.
My S/MIME appliaction does not work properly with JavaMail™ version 1.3.3. Signatures cannot be verified and encrypted messages cannot be decrypted. However, all works well with JavaMail™ 1.3.2.
There seems to be a bug in the BASE64 decoding routine used by JavaMail™ version 1.3.3. For that reason base64 encoded MIME parts cannot be properly decoded and you may get exception messages like the one described in the following bug report. Unfortunetaly we cannot provide a workaround for this problem since base64 decoding is invoked inside the JavaMail™ library. You may use a JavaMail™ version prior 1.3.3 (e.g. 1.3.2) or you may switch to JavaMail™ 1.4 which already has fixed the problem. However, please note that JavaMail™ 1.4 only can be used with JDK 1.4 or later.
When using JavaMail™ 1.3.3 and running the SMimeDemo I get the following exception saying that the signature cannot be verifie
java.security.SignatureException: Signature verification error: iaik.cms.CMSSignatureException: SignerInfo does not exist. Wrong index.
at demo.smime.DumpMessage.dump(DumpMessage.java:118)
at demo.smime.SMimeV3Demo.start(SMimeDemo.java:213)
at demo.smime.SMimeV3Demo.main(SMimeDemo.java:882)
java.lang.RuntimeException
at demo.smime.SMimeV3Demo.start(SMimeDemo.java:465)
at demo.smime.SMimeV3Demo.main(SMimeDemo.java:882)
A: Due to a bug in the BASE64 decoding routine used by JavaMail™ version 1.3.3 the SignedData object cannot be decoded corretly. For that reason it is not possible to verify the signature. Unfortunetaly we cannot provide a workaround for this problem since base64 decoding is invoked inside the JavaMail™ library. You may a JavaMail™ version prior 1.3.3 (e.g. 1.3.2) or you may switch to JavaMail™ 1.4 which already has fixed the problem. However, please note that JavaMail™ 1.4 only can be used with JDK 1.4 or later.
I have used the S/MIME library of IAIK-CMS to create and sign a multipart/mixed MIME entity consisting of only one body part:
Content-Type: multipart/mixed;
boundary="----=_Part_0_1551868.1088869295069"
——=_Part_0_1551868.1088869295069
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hello world !
——=_Part_0_1551868.1088869295069–
Athough I have no problems to display the message and verify the signature when using Mozilla, both Outlook Express and Outlook are not able to handle the message.
For some reason Outlook Express and Outlook seem to have problems with multipart/signed messages where the content consists of a multipart/mixed MIME entity that contains only one body part. However, when creating an implicit signed message (application/pkcs7-mime), Outlook and Outlook Express are able to handle the message, too. So you may either create an application/pkcs7-mime message:
boolean implicit = true;
SignedContent sc = new SignedContent(implicit);
or not to use a multipart/mixed entity that only consists of one body part with an explicit SignedContent object (multipart/signed). For your sample you may immediately call method setText of class SignedContent:
boolean implicit = false;
SignedContent sc = new SignedContent(false);
sc.setText(“Hello world !”);
I have used the S/MIME library of IAIK-CMS to create and send a triple wrapped (signed-encrypted-signed) message to an Outlook Express mail client. Outlook express is able to resolve and display the message, but complains that the signature is not correct. For the signed parts I have used the “multipart/signed” content type (explicit SignedContent).
For some reason some versions of Outlook Express seem to have problems when verifying the signatures of nested multipart/signed messages. You may use the application/pkcs7-mime (signed-data) content type by creating implicit SignedContent objects.
I have used the S/MIME library of IAIK-CMS to create and send a signed message to an Outlook Express mail client. I have included my encryption certificate into the SignedData message, but Outlook Express is not able to fetch it from the certificates field. I am using different certificates for signing and encryption.
Some versions of Outlook Express and Outlook 98 are not able to recognize the encryption certificate included in a signed message when separate certificates are used for signing/encryption. Some versions of MS Outlook Express even complain that the contents maybe altered. The reason for this strange behaviour is that MS uses a private attribute (OID “1.3.6.1.4.1.311.16.4”) for identifying the encryption certificate of the sender by issuer name and serial number. When adding signer information to your SignedContent object you will have to ensure to use a proper addSigner method that creates and adds the required private MS attribute to the corresponding SignerInfo object (see Javadoc™ of class SignedContent for choosing the right addSigner method). It might be noticed that S/MIMEv3 introduced new attribute (SMIMEEncryptionKeyPreference) allowing to include identification information similar to the Microsoft attribute. You may allow method addSigner to set this attribute, too.
When trying the SMimeSend demo, an exception is thrown saying that there is no data content handler for the S/MIME content types.
The mapping between S/MIME types and data content handlers is done by a RFC1524 mailcap file which is included in the IAIK-S/MIME distribution (named “mailcap”) to be copied into the lib directory of your Java™Home (e.g. C:/Java/j2re1.4.2/lib). You alternatively may register the IAIK-S/MIME mailcap file dynamically by using the default command map:
String mailcapFileName = …;
MailcapCommandMap mc = new MailcapCommandMap(mailcapFileName);
CommandMap.setDefaultCommandMap(mc);
Or you may add the IAIK mailcap entries to the default mailcap command map, e.g.:
MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap();
mc.addMailcap(“multipart/signed;; x-java-content-handler=iaik.smime.signed_content”);
mc.addMailcap(“application/x-pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content”);
mc.addMailcap(“application/x-pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content”);
mc.addMailcap(“application/pkcs7-signature;; x-java-content-handler=iaik.smime.signed_content”);
mc.addMailcap(“application/pkcs7-mime;; x-java-content-handler=iaik.smime.encrypted_content”);
mc.addMailcap(“application/x-pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content”);
mc.addMailcap(“application/pkcs10;; x-java-content-handler=iaik.smime.pkcs10_content”);
CommandMap.setDefaultCommandMap(mc);
For a more detailed description of mailcap handling consult the Javadoc™ of the Activation Framework.
When using the S/MIME library, I get a ClassCastException to iaik.asn1.structures. Name from the Java™ JarVerifier:
java.lang.ClassCastException: iaik.asn1.structures.Name
at sun.security.pkcs.PKCS7.getCertificate(PKCS7.java:569)
at sun.security.pkcs.SignerInfo.getCertificate(SignerInfo.java:198)
at sun.security.pkcs.SignerInfo.verify(SignerInfo.java:324)
at sun.security.pkcs.PKCS7.verify(PKCS7.java:463)
at sun.security.pkcs.PKCS7.verify(PKCS7.java:480)
at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:143)
at java.util.jar.JarVerifier.processEntry(JarVerifier.java:279)
I am using JDK1.3 and have the IAIK-JCE crypto provider (jar file is not signed) installed as first provider.
Some versions of the JavaMail™ jar files (e.g. mail.jar) and the Java™ Activation Framework jar files (activation.jar) may be signed. Due to a bug (hardcoded cast to SUN´s distinguished name implementation) in the jar file verification mechanism of some JDK versions it may be necessary to have SUN based DSA/RSA capable providers installed before the IAIK provider when the jar file verification takes places. However, you still may use IAIK as first provider if you take care to load classes from the mail.jar and activation.jar files before installing the IAIK provider. For instance, you may register the mailcap file and create a Session object, e.g.:
// register content data handlers for S/MIME types
MailcapCommandMap mc = new MailcapCommandMap(“mailcap”);
CommandMap.setDefaultCommandMap(mc);
// create some properties and get the default Session
Properties props = new Properties();
props.put(“mail.smtp.host”, host);
Session session = Session.getDefaultInstance(props, null);
// now install IAIK as first provider
IAIK.addAsProvider();
Now MailcapCommandMap and Session are loaded from activation.jar and mail.jar, respectively, and the signatures of these two jar files are verified before the IAIK provider is installed.
When installing the IAIK-JCE provider (signed version) as first provider for IAIK-CMS and trying to do some cipher operation (e.g. with the EnvelopedData type) a stack overflow error occurs. I am using JDK 1.4.
Due to a bug in the JDK jar file verification mechanism it may be necessary that the original SUN provider is installed as first provider. So insert the IAIK provider as second provider and explicitly request an IAIK engine when calling getInstance:
Security.insertProviderAt(new IAIK(), 2);
Cipher c = Cipher.getInstance(“DES/CBC/PKCS5Padding”, “IAIK”);
Alternatively you may use static method addAsJDK14Provider of the IAIK-JCE provider main class. This method uses a work around that allows to use IAIK as first provider for JDK1.4, too:
IAIK.addAsJDK14Provider();
When using IAIK-JCE as crypto provider for IAIK-CMS and trying to do some cipher operation (e.g. with the EnvelopedData type) I get an ExceptionInInitializerError is thrown saying “Cannot set up certs for trusted CAs”. I am using JDK 1.4.
With JDK1.4 the JCE framework (JAVAX CRYPTO) has been incorporated into the standard JDK. Because of export regulations a JCE provider only maybe used with JDK1.4 (or JCE 1.2.1) if it is signed. IAIK-JCE provides signed and unsigned versions of its jar files (iaik_jce.jar, iaik_jce_full.jar). Using the unsigned version with JDK 1.4 will cause the ExceptionInInitializerError “Cannot set up certs for trusted CAs”. Please use the signed jar file.
You also may ensure that the right JCE policy files are installed in the lib/security directory. due to import control restrictions of some countries, JDK1.4 per default comes with jurisdiction policy files allowing “strong” but limited cryptography; so keys that exeed the allowed strength are not allowed to be used by this policy. If you are entitled to do so, you may download and install an “unlimited strengh” version of these files. Usually, you can download them from the same web page as the Java™ runtime or JDK. Usually these files have to be put into the lib/security subdirectory of your JRE; however some VMs (e.g. IBM) may require to put them into another directory (e.g. lib/ext). Please read the installation instructions that come with these policy files. Take care to install these policy files in the correct JRE installation. Note that many JDKs install two JREs by default and that the one which is used by default is not(!) the one embedded in the JDK directory. To see which one is used, you may type java™ -verbose -version.