Package org.jose4j.jwe

Source Code of org.jose4j.jwe.WrappingKeyManagementAlgorithm

package org.jose4j.jwe;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jose4j.jwa.AlgorithmInfo;
import org.jose4j.jwx.Headers;
import org.jose4j.lang.ByteUtil;
import org.jose4j.lang.JoseException;

import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;

/**
*/
public abstract class WrappingKeyManagementAlgorithm extends AlgorithmInfo implements KeyManagementAlgorithm
{
    protected final Log log = LogFactory.getLog(this.getClass());

    private AlgorithmParameterSpec algorithmParameterSpec;

    public WrappingKeyManagementAlgorithm(String javaAlg, String alg)
    {
        setJavaAlgorithm(javaAlg);
        setAlgorithmIdentifier(alg);
    }

    public void setAlgorithmParameterSpec(AlgorithmParameterSpec algorithmParameterSpec)
    {
        this.algorithmParameterSpec = algorithmParameterSpec;
    }

    public ContentEncryptionKeys manageForEncrypt(Key managementKey, ContentEncryptionKeyDescriptor cekDesc, Headers headers, byte[] cekOverride) throws JoseException
    {
        byte[] contentEncryptionKey = cekOverride == null ? ByteUtil.randomBytes(cekDesc.getContentEncryptionKeyByteLength()) : cekOverride;
        return manageForEnc(managementKey, cekDesc, contentEncryptionKey);
    }

    protected ContentEncryptionKeys manageForEnc(Key managementKey, ContentEncryptionKeyDescriptor cekDesc, byte[] contentEncryptionKey) throws JoseException
    {
        Cipher cipher = CipherUtil.getCipher(getJavaAlgorithm());

        try
        {
            initCipher(cipher, Cipher.WRAP_MODE, managementKey);
            String contentEncryptionKeyAlgorithm = cekDesc.getContentEncryptionKeyAlgorithm();
            byte[] encryptedKey = cipher.wrap(new SecretKeySpec(contentEncryptionKey, contentEncryptionKeyAlgorithm));
            return new ContentEncryptionKeys(contentEncryptionKey, encryptedKey);
        }
        catch (IllegalBlockSizeException | InvalidKeyException | InvalidAlgorithmParameterException e)
        {
            throw new JoseException("Unable to encrypt the Content Encryption Key: " + e, e);
        }
    }

    void initCipher(Cipher cipher, int mode, Key key) throws InvalidAlgorithmParameterException, InvalidKeyException
    {
        if (algorithmParameterSpec == null)
        {
            cipher.init(mode, key);
        }
        else
        {
            cipher.init(mode, key, algorithmParameterSpec);
        }
    }

    public Key manageForDecrypt(Key managementKey, byte[] encryptedKey, ContentEncryptionKeyDescriptor cekDesc, Headers headers) throws JoseException
    {
        Cipher cipher = CipherUtil.getCipher(getJavaAlgorithm());

        try
        {
            initCipher(cipher, Cipher.UNWRAP_MODE, managementKey);
        }
        catch (InvalidKeyException | InvalidAlgorithmParameterException e)
        {
            throw new JoseException("Unable to initialize cipher for key decryption", e);
        }

        String cekAlg = cekDesc.getContentEncryptionKeyAlgorithm();

        try
        {
            return cipher.unwrap(encryptedKey, cekAlg, Cipher.SECRET_KEY);
        }
        catch (Exception e)
        {
            if (log.isDebugEnabled())
            {
                log.debug("Key unwrap failed. Substituting a randomly generated CEK and proceeding.", e);
            }

            /*
                TODO - is this good enough for step 10 from
                http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-14#section-5.2
                ?  And should it be doing this for the other key wrapping/encrypting algs? OAEP and AES Key wrap?
                    To mitigate the attacks described in RFC 3218 [RFC3218], the
                    recipient MUST NOT distinguish between format, padding, and
                    length errors of encrypted keys.  It is strongly recommended, in
                    the event of receiving an improperly formatted key, that the
                    receiver substitute a randomly generated CEK and proceed to the
                    next step, to mitigate timing attacks.
             */
            byte[] bytes = ByteUtil.randomBytes(cekDesc.getContentEncryptionKeyByteLength());
            return new SecretKeySpec(bytes, cekAlg);
        }
    }
}
TOP

Related Classes of org.jose4j.jwe.WrappingKeyManagementAlgorithm

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.