Skip to content

Signing and Encryption

Yash edited this page Sep 14, 2020 · 2 revisions

Algorithms and key specifications for S/MIME

The following algorithms and keys must be used with the specified key lengths7:

SIGNATURE key length
Hash algorithm SHA-256 or SHA-512 (in accordance with IETF RFC 5754).
Signature algorithm RSA key length at least 2048 bit
RSASSA-PSS (in accordance with IETF RFC 4056)
ENCRYPTION key length
Content encryption AES-128 CBC or AES-192 CBC (in accordance with IETF RFC 3565) or AES-256 CBC
Key encryption RSA key length at least 2048 bit.
RSAES-OAEP (in accordance with IETF RFC 8017). Key encryption has hash functions as parameters.
private X509Certificate[] signerCertificatesChain;
protected HashMap<String, Object> buildCertificateAndGetPrivateKey(InputStream is, String password) throws Exception {
    HashMap<String, Object> certificateDataHashMap = new HashMap<String, Object>();
    // org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access:
    // this web application instance has been stopped already. YASH: https://stackoverflow.com/a/61952755/5081877
    KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");

    if (password == null) {
        keystore.load(is, null);
    } else {
        keystore.load(is, password.toCharArray());
    }

    Enumeration<String> keyStoreAliasEnum = keystore.aliases();
    PrivateKey privateKey = null;
    String alias = null;
    if (keyStoreAliasEnum.hasMoreElements()) {
        alias = keyStoreAliasEnum.nextElement();
        if (password != null) {
            privateKey = (PrivateKey) keystore.getKey(alias, password.toCharArray());
        }
    }

    CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
    Certificate certificate = keystore.getCertificate(alias);
    ByteArrayInputStream bais = new ByteArrayInputStream(certificate.getEncoded());
    X509Certificate x509Certificate = (X509Certificate) cf.generateCertificate(bais);

    Certificate[] chain = (Certificate[]) keystore.getCertificateChain(alias);

    if (chain != null) {
        signerCertificatesChain = new X509Certificate[chain.length];
        for (int i = 0; i < chain.length; i++) {
            signerCertificatesChain[i] = (X509Certificate) chain[i];
        }
    }
    certificateDataHashMap.put("certificate", x509Certificate);
    certificateDataHashMap.put("certificatePrivateKey", privateKey);
    return certificateDataHashMap;
}
public SMIMESignedGenerator createSignerUsingBouncyCastle() {
    SMIMECapabilityVector capabilities = new SMIMECapabilityVector();
    capabilities.addCapability(SMIMECapability.dES_EDE3_CBC);
    capabilities.addCapability(SMIMECapability.rC2_CBC, 128);
    capabilities.addCapability(SMIMECapability.dES_CBC);
    //capabilities.addCapability(SMIMECapability.aES256_CBC);

    ASN1EncodableVector attributes = new ASN1EncodableVector();
    attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(SMIMEUtil.createIssuerAndSerialNumberFor(signerCertificate)));
    attributes.add(new SMIMECapabilitiesAttribute(capabilities));

    SMIMESignedGenerator signer = new SMIMESignedGenerator();
    signer.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC")
                    .setSignedAttributeGenerator(new AttributeTable(attributes))
                    .build(signerCertificate.getSigAlgName(), signerPrivateKey, signerCertificate));

    List<X509Certificate> certList = Arrays.asList(signerCertificatesChain);
    Store certs;
    /** Add the list of certs to the generator */
    certs = new JcaCertStore(certList);
    signer.addCertificates(certs);
    return signer;
}

RSAES_OAEP as Key encryption Example:

private MimeBodyPart getEncryptedPart(MimeMessage message) {
    JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
    OAEPParameterSpec oaepParameters = new javax.crypto.spec.OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);
    AlgorithmIdentifier idRsaOaep = null;
    try {
        idRsaOaep = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepParameters);
        log.info("AlgorithmIdentifier : "+idRsaOaep.toString());
    } catch (InvalidAlgorithmParameterException e) {
        e.printStackTrace();
    }
    encrypter.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(recipientCertificate, idRsaOaep).setProvider("BC"));
    return encrypter.generate(message, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC, 256).setProvider("BC").build());
}

Clone this wiki locally