All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nimbusds.jose.crypto.AESGCMKW Maven / Gradle / Ivy

Go to download

Java library for Javascript Object Signing and Encryption (JOSE) and JSON Web Tokens (JWT)

There is a newer version: 10.0.2
Show newest version
package com.nimbusds.jose.crypto;


import java.security.Provider;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import net.jcip.annotations.ThreadSafe;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;

import com.nimbusds.jose.JOSEException;


/**
 * AES GCM methods for Content Encryption Key (CEK) encryption and
 * decryption. Uses the BouncyCastle.org provider. This class is thread-safe.
 *
 * 

See draft-ietf-jose-json-web-algorithms-26, section 4.7. * * @author Melisa Halsband * @version $version$ (2014-06-18) */ @ThreadSafe class AESGCMKW { /** * The standard authentication tag length (128 bits). */ public static final int AUTH_TAG_BIT_LENGTH = 128; /** * Encrypts the specified Content Encryption Key (CEK). * * @param cek The Content Encryption Key (CEK) to encrypt. Must * not be {@code null}. * @param iv The initialisation vector (IV). Must not be * {@code null}. * @param kek The AES Key Encription Key (KEK). Must not be * {@code null}. * @param provider The JCA provider, or {@code null} to use the default * one. * * @return The encrypted Content Encryption Key (CEK). * * @throws JOSEException If encryption failed. */ public static AuthenticatedCipherText encryptCEK(final SecretKey cek, final byte[] iv, final SecretKey kek, Provider provider) throws JOSEException { // Initialise AES cipher BlockCipher cipher = AES.createCipher(kek, true); // Create GCM cipher with AES GCMBlockCipher gcm = new GCMBlockCipher(cipher); AEADParameters aeadParams = new AEADParameters(new KeyParameter(kek.getEncoded()), AUTH_TAG_BIT_LENGTH, iv, null); gcm.init(true, aeadParams); // Prepare output buffer int outputLength = gcm.getOutputSize(cek.getEncoded().length); byte[] output = new byte[outputLength]; // Produce cipher text int outputOffset = gcm.processBytes(cek.getEncoded(), 0, cek.getEncoded().length, output, 0); // Produce authentication tag try { outputOffset += gcm.doFinal(output, outputOffset); } catch (InvalidCipherTextException e) { throw new JOSEException("Couldn't generate GCM authentication tag for key: " + e.getMessage(), e); } // Split output into cipher text and authentication tag int authTagLength = AUTH_TAG_BIT_LENGTH / 8; byte[] cipherText = new byte[outputOffset - authTagLength]; byte[] authTag = new byte[authTagLength]; System.arraycopy(output, 0, cipherText, 0, cipherText.length); System.arraycopy(output, outputOffset - authTagLength, authTag, 0, authTag.length); return new AuthenticatedCipherText(cipherText, authTag); } /** * Decrypts the specified encrypted Content Encryption Key (CEK). * * @param kek The AES Key Encription Key. Must not be * {@code null}. * @param iv The initialisation vector (IV). Must not be * {@code null}. * @param authEncrCEK The encrypted Content Encryption Key (CEK) to * decrypt and authentication tag. Must not be * {@code null}. * @param provider The JCA provider, or {@code null} to use the * default one. * * @return The decrypted Content Encryption Key (CEK). * * @throws JOSEException If decryption failed. */ public static SecretKey decryptCEK(final SecretKey kek, final byte[] iv, final AuthenticatedCipherText authEncrCEK, final int keyLength, final Provider provider) throws JOSEException { // Initialise AES cipher BlockCipher cipher = AES.createCipher(kek, false); // Create GCM cipher with AES GCMBlockCipher gcm = new GCMBlockCipher(cipher); AEADParameters aeadParams = new AEADParameters(new KeyParameter(kek.getEncoded()), AUTH_TAG_BIT_LENGTH, iv, null); gcm.init(false, aeadParams); byte[] cipherText = authEncrCEK.getCipherText(); byte[] authTag = authEncrCEK.getAuthenticationTag(); // Join encrypted CEK and authentication tag to produce cipher input byte[] input = new byte[cipherText.length + authTag.length]; System.arraycopy(cipherText, 0, input, 0, cipherText.length); System.arraycopy(authTag, 0, input, cipherText.length, authTag.length); int keyBytesLength = gcm.getOutputSize(input.length); byte[] keyBytes = new byte[keyBytesLength]; // Decrypt int keyBytesOffset = gcm.processBytes(input, 0, input.length, keyBytes, 0); // Validate authentication tag try { keyBytesOffset += gcm.doFinal(keyBytes, keyBytesOffset); } catch (InvalidCipherTextException e) { throw new JOSEException("Couldn't validate GCM authentication tag: " + e.getMessage(), e); } if (8 * keyBytes.length != keyLength) { throw new JOSEException("CEK key length mismatch: " + keyBytes.length + " != " + keyLength); } return new SecretKeySpec(keyBytes, "AES"); } /** * Prevents public instantiation. */ private AESGCMKW() { } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy