/** * Returns the byte length of the specified byte array, preventing * integer overflow. * * @param byteArray The byte array. May be {@code null}. * * @return The bite length, zero if the array is {@code null}. * * @throws IntegerOverflowException On a integer overflow. */ public static int safeBitLength(final byte[] byteArray) throws IntegerOverflowException { if (byteArray == null) { return 0; } else { return safeBitLength(byteArray.length); } }
/** * Computes the bit length of the specified Additional Authenticated * Data (AAD). Used in AES/CBC/PKCS5Padding/HMAC-SHA2 encryption. * * @param aad The Additional Authenticated Data (AAD). Must not be * {@code null}. * * @return The computed AAD bit length, as a 64 bit big-endian * representation (8 byte array). * * @throws IntegerOverflowException On a integer overflow. */ public static byte[] computeLength(final byte[] aad) throws IntegerOverflowException { final int bitLength = ByteUtils.safeBitLength(aad); return ByteBuffer.allocate(8).putLong(bitLength).array(); } }
/** * Validates the specified IV and authentication tag according to the * AES GCM requirements in * <a href="https://tools.ietf.org/html/rfc7518#section-5.3">JWA RFC</a>. * * @param iv The IV to check for compliance. * @param authTagLength The authentication tag length to check for * compliance. * * @throws JOSEException If the parameters don't match the JWA * requirements. * * @see #IV_BIT_LENGTH * @see #AUTH_TAG_BIT_LENGTH */ private static void validate(final byte[] iv, final int authTagLength) throws JOSEException { if (ByteUtils.safeBitLength(iv) != IV_BIT_LENGTH) { throw new JOSEException(String.format("IV length of %d bits is required, got %d", IV_BIT_LENGTH, ByteUtils.safeBitLength(iv))); } if (authTagLength != AUTH_TAG_BIT_LENGTH) { throw new JOSEException(String.format("Authentication tag length of %d bits is required, got %d", AUTH_TAG_BIT_LENGTH, authTagLength)); } }
@Override public int size() { try { return ByteUtils.safeBitLength(k.decode()); } catch (IntegerOverflowException e) { throw new ArithmeticException(e.getMessage()); } }
@Override public int size() { try { return ByteUtils.safeBitLength(n.decode()); } catch (IntegerOverflowException e) { throw new ArithmeticException(e.getMessage()); } }
byte[] secretKeyBytes = cipher.doFinal(encryptedCEK); if (ByteUtils.safeBitLength(secretKeyBytes) != keyLength) {
/** * 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 { byte[] keyBytes = AESGCM.decrypt(kek, iv, authEncrCEK.getCipherText(), new byte[0], authEncrCEK.getAuthenticationTag(), provider); if (ByteUtils.safeBitLength(keyBytes) != keyLength) { throw new KeyLengthException("CEK key length mismatch: " + ByteUtils.safeBitLength(keyBytes) + " != " + keyLength); } return new SecretKeySpec(keyBytes, "AES"); }
for (int i=1; i <= computeDigestCycles(ByteUtils.safeBitLength(md.getDigestLength()), keyLengthBits); i++) {
/** * Checks the length of the Content Encryption Key (CEK) according to * the encryption method. * * @param cek The CEK. Must not be {@code null}. * @param enc The encryption method. Must not be {@code null}. * * @throws KeyLengthException If the CEK length doesn't match the * encryption method. */ private static void checkCEKLength(final SecretKey cek, final EncryptionMethod enc) throws KeyLengthException { try { if (enc.cekBitLength() != ByteUtils.safeBitLength(cek.getEncoded())) { throw new KeyLengthException("The Content Encryption Key (CEK) length for " + enc + " must be " + enc.cekBitLength() + " bits"); } } catch (IntegerOverflowException e) { throw new KeyLengthException("The Content Encryption Key (CEK) is too long: " + e.getMessage()); } }
@Override public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText) throws JOSEException { JWEAlgorithm alg = header.getAlgorithm(); if (! alg.equals(JWEAlgorithm.DIR)) { throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS)); } // Check key length matches encryption method EncryptionMethod enc = header.getEncryptionMethod(); if (enc.cekBitLength() != ByteUtils.safeBitLength(getKey().getEncoded())) { throw new KeyLengthException(enc.cekBitLength(), enc); } final Base64URL encryptedKey = null; // The second JWE part return ContentCryptoProvider.encrypt(header, clearText, getKey(), encryptedKey, getJCAContext()); } }
if(ByteUtils.safeBitLength(getKey().getEncoded()) != 128){ throw new KeyLengthException("The Key Encryption Key (KEK) length must be 128 bits for A128KW encryption"); if(ByteUtils.safeBitLength(getKey().getEncoded()) != 192){ throw new KeyLengthException("The Key Encryption Key (KEK) length must be 192 bits for A192KW encryption"); if (ByteUtils.safeBitLength(getKey().getEncoded()) != 256) { throw new KeyLengthException("The Key Encryption Key (KEK) length must be 256 bits for A256KW encryption"); if(ByteUtils.safeBitLength(getKey().getEncoded()) != 128){ throw new KeyLengthException("The Key Encryption Key (KEK) length must be 128 bits for A128GCMKW encryption"); if(ByteUtils.safeBitLength(getKey().getEncoded()) != 192){ throw new KeyLengthException("The Key Encryption Key (KEK) length must be 192 bits for A192GCMKW encryption"); if(ByteUtils.safeBitLength(getKey().getEncoded()) != 256){ throw new KeyLengthException("The Key Encryption Key (KEK) length must be 256 bits for A256GCMKW encryption");