public String encryptWith( List<JweEncryptionProvider> encryptors, List<JweHeaders> recipientUnprotected) { checkAndGetContentAlgorithm(encryptors); if (recipientUnprotected != null && recipientUnprotected.size() != encryptors.size()) { throw new IllegalArgumentException(); } JweHeaders unionHeaders = new JweHeaders(); if (protectedHeader != null) { unionHeaders.asMap().putAll(protectedHeader.asMap()); } if (unprotectedHeader != null) { if (!Collections.disjoint( unionHeaders.asMap().keySet(), unprotectedHeader.asMap().keySet())) { LOG.warning("Protected and unprotected headers have duplicate values"); throw new JweException(JweException.Error.INVALID_JSON_JWE); } checkCriticalHeaders(unprotectedHeader); unionHeaders.asMap().putAll(unprotectedHeader.asMap()); } List<JweJsonEncryptionEntry> entries = new ArrayList<JweJsonEncryptionEntry>(encryptors.size()); Map<String, Object> jweJsonMap = new LinkedHashMap<String, Object>(); byte[] cipherText = null; byte[] authTag = null; byte[] iv = null; for (int i = 0; i < encryptors.size(); i++) { JweEncryptionProvider encryptor = encryptors.get(i); JweHeaders perRecipientUnprotected = recipientUnprotected == null ? null : recipientUnprotected.get(i); JweHeaders jsonHeaders = null; if (perRecipientUnprotected != null) { checkCriticalHeaders(perRecipientUnprotected); if (!Collections.disjoint( unionHeaders.asMap().keySet(), perRecipientUnprotected.asMap().keySet())) { LOG.warning("union and recipient unprotected headers have duplicate values"); throw new JweException(JweException.Error.INVALID_JSON_JWE); } jsonHeaders = new JweHeaders(unionHeaders.asMap()); jsonHeaders.asMap().putAll(perRecipientUnprotected.asMap()); } else { jsonHeaders = unionHeaders; } jsonHeaders.setProtectedHeaders(protectedHeader); JweEncryptionInput input = createEncryptionInput(jsonHeaders); if (i > 0) { input.setContent(null); } JweEncryptionOutput state = encryptor.getEncryptionOutput(input); byte[] currentCipherText = state.getEncryptedContent(); byte[] currentAuthTag = state.getAuthTag(); byte[] currentIv = state.getIv(); if (cipherText == null) { cipherText = currentCipherText; } if (authTag == null) { authTag = currentAuthTag; } if (iv == null) { iv = currentIv; } byte[] encryptedCek = state.getContentEncryptionKey(); if (encryptedCek.length == 0 && encryptor.getKeyAlgorithm() != null) { LOG.warning("Unexpected key encryption algorithm"); throw new JweException(JweException.Error.INVALID_JSON_JWE); } String encodedCek = encryptedCek.length == 0 ? null : Base64UrlUtility.encode(encryptedCek); entries.add(new JweJsonEncryptionEntry(perRecipientUnprotected, encodedCek)); } if (protectedHeader != null) { jweJsonMap.put("protected", Base64UrlUtility.encode(writer.toJson(protectedHeader))); } if (unprotectedHeader != null) { jweJsonMap.put("unprotected", unprotectedHeader); } if (entries.size() == 1 && canBeFlat) { JweHeaders unprotectedEntryHeader = entries.get(0).getUnprotectedHeader(); if (unprotectedEntryHeader != null) { jweJsonMap.put("header", unprotectedEntryHeader); } String encryptedKey = entries.get(0).getEncodedEncryptedKey(); if (encryptedKey != null) { jweJsonMap.put("encrypted_key", encryptedKey); } } else { jweJsonMap.put("recipients", entries); } if (aad != null) { jweJsonMap.put("aad", Base64UrlUtility.encode(aad)); } jweJsonMap.put("iv", Base64UrlUtility.encode(iv)); jweJsonMap.put("ciphertext", Base64UrlUtility.encode(cipherText)); jweJsonMap.put("tag", Base64UrlUtility.encode(authTag)); return writer.toJson(jweJsonMap); }
private static void checkCriticalHeaders(JweHeaders unprotected) { if (unprotected.asMap().containsKey(JoseConstants.HEADER_CRITICAL)) { LOG.warning("Unprotected headers contain critical headers"); throw new JweException(JweException.Error.INVALID_JSON_JWE); } }