Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 675AC176DC for ; Mon, 6 Oct 2014 17:25:55 +0000 (UTC) Received: (qmail 71665 invoked by uid 500); 6 Oct 2014 17:25:55 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 71497 invoked by uid 500); 6 Oct 2014 17:25:55 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 70955 invoked by uid 99); 6 Oct 2014 17:25:54 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 06 Oct 2014 17:25:54 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8D490320858; Mon, 6 Oct 2014 17:25:54 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Date: Mon, 06 Oct 2014 17:26:01 -0000 Message-Id: In-Reply-To: <79b7abeb12ab45d582d930154a5c047b@git.apache.org> References: <79b7abeb12ab45d582d930154a5c047b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [08/10] [CXF-5944] Finalizing the current round of refactorings with introducing a dedicated rt rs security module, idea from Luigi Lo Iacono http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.java new file mode 100644 index 0000000..ccf7ce7 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentDecryptionAlgorithm.java @@ -0,0 +1,24 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + +public interface ContentDecryptionAlgorithm extends ContentEncryptionCipherProperties { + byte[] getEncryptedSequence(JweHeaders headers, byte[] cipher, byte[] authTag); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java new file mode 100644 index 0000000..07b370e --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionAlgorithm.java @@ -0,0 +1,27 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + + +public interface ContentEncryptionAlgorithm extends ContentEncryptionCipherProperties { + String getAlgorithm(); + byte[] getInitVector(); + byte[] getContentEncryptionKey(JweHeaders headers); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java new file mode 100644 index 0000000..54da6fd --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/ContentEncryptionCipherProperties.java @@ -0,0 +1,27 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.security.spec.AlgorithmParameterSpec; + + +public interface ContentEncryptionCipherProperties { + byte[] getAdditionalAuthenticationData(String headersJson); + AlgorithmParameterSpec getAlgorithmParameterSpec(byte[] iv); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..c1803c6 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyDecryptionAlgorithm.java @@ -0,0 +1,39 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.security.Key; + +public class DirectKeyDecryptionAlgorithm implements KeyDecryptionAlgorithm { + private byte[] contentDecryptionKey; + public DirectKeyDecryptionAlgorithm(Key contentDecryptionKey) { + this(contentDecryptionKey.getEncoded()); + } + public DirectKeyDecryptionAlgorithm(byte[] contentDecryptionKey) { + this.contentDecryptionKey = contentDecryptionKey; + } + @Override + public byte[] getDecryptedContentEncryptionKey(JweCompactConsumer consumer) { + byte[] encryptedCEK = consumer.getEncryptedContentEncryptionKey(); + if (encryptedCEK != null && encryptedCEK.length > 0) { + throw new SecurityException(); + } + return contentDecryptionKey; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..6714c3c --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyEncryptionAlgorithm.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + +public class DirectKeyEncryptionAlgorithm implements KeyEncryptionAlgorithm { + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] theCek) { + if (headers.getKeyEncryptionAlgorithm() != null) { + throw new SecurityException(); + } + return new byte[0]; + } + + @Override + public String getAlgorithm() { + return null; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java new file mode 100644 index 0000000..6c822ea --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweDecryption.java @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.security.Key; + +import org.apache.cxf.rs.security.jose.JoseHeadersReader; + +public class DirectKeyJweDecryption extends AbstractJweDecryption { + public DirectKeyJweDecryption(Key contentDecryptionKey, + ContentDecryptionAlgorithm cipherProps) { + this(contentDecryptionKey, null, cipherProps); + } + public DirectKeyJweDecryption(Key contentDecryptionKey, + JoseHeadersReader reader, + ContentDecryptionAlgorithm cipherProps) { + super(reader, + new DirectKeyDecryptionAlgorithm(contentDecryptionKey), + cipherProps); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java new file mode 100644 index 0000000..b343cf4 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/DirectKeyJweEncryption.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + +public class DirectKeyJweEncryption extends AbstractJweEncryption { + + public DirectKeyJweEncryption(ContentEncryptionAlgorithm ceAlgo) { + this(new JweHeaders(ceAlgo.getAlgorithm()), ceAlgo); + } + public DirectKeyJweEncryption(JweHeaders headers, ContentEncryptionAlgorithm ceAlgo) { + super(headers, ceAlgo, new DirectKeyEncryptionAlgorithm()); + } + protected byte[] getProvidedContentEncryptionKey() { + return validateCek(super.getProvidedContentEncryptionKey()); + } + private static byte[] validateCek(byte[] cek) { + if (cek == null) { + // to prevent the cek from being auto-generated which + // does not make sense for the direct key case + throw new NullPointerException("CEK must not be null"); + } + return cek; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java new file mode 100644 index 0000000..7794102 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactConsumer.java @@ -0,0 +1,113 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.rs.security.jose.jwe; + +import java.io.UnsupportedEncodingException; + +import org.apache.cxf.common.util.Base64Exception; +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.rs.security.jose.JoseHeaders; +import org.apache.cxf.rs.security.jose.JoseHeadersReader; +import org.apache.cxf.rs.security.jose.JoseHeadersReaderWriter; + + +public class JweCompactConsumer { + private String headersJson; + private byte[] encryptedCEK; + private byte[] initVector; + private byte[] encryptedContent; + private byte[] authTag; + private JweHeaders jweHeaders; + public JweCompactConsumer(String jweContent) { + this(jweContent, new JoseHeadersReaderWriter()); + } + public JweCompactConsumer(String jweContent, JoseHeadersReader reader) { + String[] parts = jweContent.split("\\."); + if (parts.length != 5) { + throw new SecurityException("5 JWE parts are expected"); + } + try { + headersJson = new String(Base64UrlUtility.decode(parts[0])); + encryptedCEK = Base64UrlUtility.decode(parts[1]); + initVector = Base64UrlUtility.decode(parts[2]); + + encryptedContent = Base64UrlUtility.decode(parts[3]); + authTag = Base64UrlUtility.decode(parts[4]); + JoseHeaders joseHeaders = reader.fromJsonHeaders(headersJson); + if (joseHeaders.getHeaderUpdateCount() != null) { + throw new SecurityException(); + } + jweHeaders = new JweHeaders(joseHeaders); + + } catch (Base64Exception ex) { + throw new SecurityException(ex); + } + } + + public String getDecodedJsonHeaders() { + return headersJson; + } + + public JweHeaders getJweHeaders() { + return jweHeaders; + } + + public byte[] getEncryptedContentEncryptionKey() { + return encryptedCEK; + } + + public byte[] getContentDecryptionCipherInitVector() { + return initVector; + } + + public byte[] getContentEncryptionCipherAAD() { + return JweHeaders.toCipherAdditionalAuthData(headersJson); + } + + public byte[] getEncryptionAuthenticationTag() { + return authTag; + } + + public byte[] getEncryptedContent() { + return encryptedContent; + } + + public byte[] getEncryptedContentWithAuthTag() { + return getCipherWithAuthTag(encryptedContent, authTag); + } + + public static byte[] getCipherWithAuthTag(byte[] cipher, byte[] authTag) { + byte[] encryptedContentWithTag = new byte[cipher.length + authTag.length]; + System.arraycopy(cipher, 0, encryptedContentWithTag, 0, cipher.length); + System.arraycopy(authTag, 0, encryptedContentWithTag, cipher.length, authTag.length); + return encryptedContentWithTag; + } + + public byte[] getDecryptedContent(JweDecryptionProvider decryption) { + return decryption.decrypt(this); + } + public String getDecryptedContentText(JweDecryptionProvider decryption) { + try { + return new String(getDecryptedContent(decryption), "UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new SecurityException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java new file mode 100644 index 0000000..176081b --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweCompactProducer.java @@ -0,0 +1,156 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.rs.security.jose.jwe; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.rs.security.jose.JoseHeadersReaderWriter; +import org.apache.cxf.rs.security.jose.JoseHeadersWriter; +import org.apache.cxf.rs.security.jose.jwt.JwtTokenReaderWriter; + + +public class JweCompactProducer { + private StringBuilder jweContentBuilder; + private String encodedEncryptedContent; + private String encodedAuthTag; + public JweCompactProducer(JweHeaders headers, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentNoTag, + byte[] authenticationTag) { + this(headers, null, encryptedContentEncryptionKey, + cipherInitVector, encryptedContentNoTag, authenticationTag); + } + + public JweCompactProducer(JweHeaders headers, + JoseHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentNoTag, + byte[] authenticationTag) { + this(getHeadersJson(headers, writer), + encryptedContentEncryptionKey, + cipherInitVector, + encryptedContentNoTag, + authenticationTag); + } + public JweCompactProducer(String headersJson, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentNoTag, + byte[] authenticationTag) { + jweContentBuilder = startJweContent(new StringBuilder(), headersJson, + encryptedContentEncryptionKey, cipherInitVector); + this.encodedEncryptedContent = Base64UrlUtility.encode(encryptedContentNoTag); + this.encodedAuthTag = Base64UrlUtility.encode(authenticationTag); + + } + + public JweCompactProducer(JweHeaders headers, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentWithTag, + int authTagLengthBits) { + this(headers, null, encryptedContentEncryptionKey, + cipherInitVector, encryptedContentWithTag, authTagLengthBits); + } + public JweCompactProducer(JweHeaders headers, + JoseHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector, + byte[] encryptedContentWithTag, + int authTagLengthBits) { + jweContentBuilder = startJweContent(new StringBuilder(), headers, writer, + encryptedContentEncryptionKey, cipherInitVector); + this.encodedEncryptedContent = Base64UrlUtility.encodeChunk( + encryptedContentWithTag, + 0, + encryptedContentWithTag.length - authTagLengthBits / 8); + this.encodedAuthTag = Base64UrlUtility.encodeChunk( + encryptedContentWithTag, + encryptedContentWithTag.length - authTagLengthBits / 8, + authTagLengthBits / 8); + + } + public static String startJweContent(JweHeaders headers, + JoseHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + return startJweContent(new StringBuilder(), + headers, writer, encryptedContentEncryptionKey, cipherInitVector).toString(); + } + public static StringBuilder startJweContent(StringBuilder sb, + JweHeaders headers, + JoseHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + return startJweContent(sb, + getHeadersJson(headers, writer), + encryptedContentEncryptionKey, + cipherInitVector); + } + private static String getHeadersJson(JweHeaders headers, + JoseHeadersWriter writer) { + writer = writer == null ? new JoseHeadersReaderWriter() : writer; + return writer.headersToJson(headers); + + } + public static StringBuilder startJweContent(StringBuilder sb, + String headersJson, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) { + String encodedHeaders = Base64UrlUtility.encode(headersJson); + String encodedContentEncryptionKey = Base64UrlUtility.encode(encryptedContentEncryptionKey); + String encodedInitVector = Base64UrlUtility.encode(cipherInitVector); + sb.append(encodedHeaders) + .append('.') + .append(encodedContentEncryptionKey == null ? "" : encodedContentEncryptionKey) + .append('.') + .append(encodedInitVector == null ? "" : encodedInitVector) + .append('.'); + return sb; + } + + public static void startJweContent(OutputStream os, + JweHeaders headers, + JoseHeadersWriter writer, + byte[] encryptedContentEncryptionKey, + byte[] cipherInitVector) throws IOException { + writer = writer == null ? new JwtTokenReaderWriter() : writer; + byte[] jsonBytes = writer.headersToJson(headers).getBytes("UTF-8"); + Base64UrlUtility.encodeAndStream(jsonBytes, 0, jsonBytes.length, os); + byte[] dotBytes = new byte[]{'.'}; + os.write(dotBytes); + Base64UrlUtility.encodeAndStream(encryptedContentEncryptionKey, 0, + encryptedContentEncryptionKey.length, os); + os.write(dotBytes); + Base64UrlUtility.encodeAndStream(cipherInitVector, 0, cipherInitVector.length, os); + os.write(dotBytes); + } + + public String getJweContent() { + return jweContentBuilder.append(encodedEncryptedContent) + .append('.') + .append(encodedAuthTag) + .toString(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java new file mode 100644 index 0000000..f3cf255 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionOutput.java @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.io.UnsupportedEncodingException; + +public class JweDecryptionOutput { + private JweHeaders headers; + private byte[] content; + public JweDecryptionOutput(JweHeaders headers, byte[] content) { + this.headers = headers; + this.content = content; + } + public JweHeaders getHeaders() { + return headers; + } + public byte[] getContent() { + return content; + } + public String getContentText() { + try { + return new String(getContent(), "UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new SecurityException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java new file mode 100644 index 0000000..d20401b --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweDecryptionProvider.java @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + + +public interface JweDecryptionProvider { + JweDecryptionOutput decrypt(String jweContent); + byte[] decrypt(JweCompactConsumer consumer); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java new file mode 100644 index 0000000..5b9afee --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionProvider.java @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + + +public interface JweEncryptionProvider { + String encrypt(byte[] jweContent, String contentType); + JweEncryptionState createJweEncryptionState(String contentType); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java new file mode 100644 index 0000000..0732250 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweEncryptionState.java @@ -0,0 +1,63 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import javax.crypto.Cipher; + +public class JweEncryptionState { + private Cipher cipher; + private JweHeaders headers; + private byte[] contentEncryptionKey; + private byte[] iv; + private boolean compressionSupported; + private AuthenticationTagProducer authTagProducer; + + public JweEncryptionState(Cipher cipher, + JweHeaders headers, + byte[] contentEncryptionKey, + byte[] iv, + AuthenticationTagProducer authTagProducer, + boolean compressionSupported) { + this.cipher = cipher; + this.headers = headers; + this.contentEncryptionKey = contentEncryptionKey; + this.iv = iv; + this.authTagProducer = authTagProducer; + this.compressionSupported = compressionSupported; + } + public Cipher getCipher() { + return cipher; + } + public JweHeaders getHeaders() { + return headers; + } + public byte[] getContentEncryptionKey() { + return contentEncryptionKey; + } + public byte[] getIv() { + return iv; + } + public boolean isCompressionSupported() { + return compressionSupported; + } + public AuthenticationTagProducer getAuthTagProducer() { + return authTagProducer; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java new file mode 100644 index 0000000..f0e6d37 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweHeaders.java @@ -0,0 +1,106 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.rs.security.jose.jwe; + +import java.io.UnsupportedEncodingException; +import java.util.Map; + +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.rs.security.jose.JoseConstants; +import org.apache.cxf.rs.security.jose.JoseHeaders; +import org.apache.cxf.rs.security.jose.JoseHeadersWriter; + + + + +public class JweHeaders extends JoseHeaders { + + public JweHeaders() { + } + + public JweHeaders(JoseHeaders headers) { + super(headers.asMap()); + } + + public JweHeaders(Map values) { + super(values); + } + public JweHeaders(String keyEncAlgo, String ctEncAlgo) { + this(keyEncAlgo, ctEncAlgo, false); + } + public JweHeaders(String ctEncAlgo) { + this(null, ctEncAlgo, false); + } + public JweHeaders(String ctEncAlgo, boolean deflate) { + this(null, ctEncAlgo, deflate); + } + public JweHeaders(String keyEncAlgo, String ctEncAlgo, boolean deflate) { + init(keyEncAlgo, ctEncAlgo, deflate); + } + private void init(String keyEncAlgo, String ctEncAlgo, boolean deflate) { + if (keyEncAlgo != null) { + setKeyEncryptionAlgorithm(keyEncAlgo); + } + setContentEncryptionAlgorithm(ctEncAlgo); + if (deflate) { + setZipAlgorithm(JoseConstants.DEFLATE_ZIP_ALGORITHM); + } + } + + public void setKeyEncryptionAlgorithm(String type) { + super.setAlgorithm(type); + } + + public String getKeyEncryptionAlgorithm() { + return super.getAlgorithm(); + } + + public void setContentEncryptionAlgorithm(String type) { + setHeader(JoseConstants.JWE_HEADER_CONTENT_ENC_ALGORITHM, type); + } + + public String getContentEncryptionAlgorithm() { + return (String)getHeader(JoseConstants.JWE_HEADER_CONTENT_ENC_ALGORITHM); + } + + public void setZipAlgorithm(String type) { + setHeader(JoseConstants.JWE_HEADER_ZIP_ALGORITHM, type); + } + + public String getZipAlgorithm() { + return (String)getHeader(JoseConstants.JWE_HEADER_ZIP_ALGORITHM); + } + + @Override + public JoseHeaders setHeader(String name, Object value) { + return (JoseHeaders)super.setHeader(name, value); + } + public byte[] toCipherAdditionalAuthData(JoseHeadersWriter writer) { + return toCipherAdditionalAuthData(writer.headersToJson(this)); + } + public static byte[] toCipherAdditionalAuthData(String headersJson) { + try { + String base64UrlHeadersInJson = Base64UrlUtility.encode(headersJson.getBytes("UTF-8")); + return base64UrlHeadersInJson.getBytes("US-ASCII"); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException(ex); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java new file mode 100644 index 0000000..c6462f1 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweOutputStream.java @@ -0,0 +1,145 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +import javax.crypto.Cipher; + +import org.apache.cxf.common.util.Base64UrlUtility; + +public class JweOutputStream extends FilterOutputStream { + private Cipher encryptingCipher; + private int blockSize; + private AuthenticationTagProducer authTagProducer; + private byte[] lastRawDataChunk; + private byte[] lastEncryptedDataChunk; + private boolean flushed; + public JweOutputStream(OutputStream out, + Cipher encryptingCipher, + AuthenticationTagProducer authTagProducer) { + super(out); + this.encryptingCipher = encryptingCipher; + this.blockSize = encryptingCipher.getBlockSize(); + this.authTagProducer = authTagProducer; + } + + @Override + public void write(int value) throws IOException { + byte[] bytes = ByteBuffer.allocate(Integer.SIZE / 8).putInt(value).array(); + write(bytes, 0, bytes.length); + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + if (lastRawDataChunk != null) { + int remaining = blockSize - lastRawDataChunk.length; + int lenToCopy = remaining < len ? remaining : len; + lastRawDataChunk = newArray(lastRawDataChunk, 0, lastRawDataChunk.length, b, off, lenToCopy); + off = off + lenToCopy; + len -= lenToCopy; + if (lastRawDataChunk.length < blockSize) { + return; + } else { + encryptAndWrite(lastRawDataChunk, 0, lastRawDataChunk.length); + lastRawDataChunk = null; + } + } + int offset = 0; + int chunkSize = blockSize > len ? blockSize : blockSize * (len / blockSize); + for (; offset + chunkSize <= len; offset += chunkSize, off += chunkSize) { + encryptAndWrite(b, off, chunkSize); + } + if (offset < len) { + lastRawDataChunk = newArray(b, off, len - offset); + } + + } + + private void encryptAndWrite(byte[] chunk, int off, int len) throws IOException { + byte[] encrypted = encryptingCipher.update(chunk, off, len); + if (authTagProducer != null) { + authTagProducer.update(encrypted, 0, encrypted.length); + } + encodeAndWrite(encrypted, 0, encrypted.length, false); + } + private void encodeAndWrite(byte[] encryptedChunk, int off, int len, boolean finalWrite) throws IOException { + byte[] theChunk = lastEncryptedDataChunk; + int lenToEncode = len; + if (theChunk != null) { + theChunk = newArray(theChunk, 0, theChunk.length, encryptedChunk, off, len); + lenToEncode = theChunk.length; + off = 0; + } else { + theChunk = encryptedChunk; + } + int rem = finalWrite ? 0 : lenToEncode % 3; + Base64UrlUtility.encodeAndStream(theChunk, off, lenToEncode - rem, out); + + if (rem > 0) { + lastEncryptedDataChunk = newArray(theChunk, lenToEncode - rem, rem); + } else { + lastEncryptedDataChunk = null; + } + } + + @Override + public void flush() throws IOException { + if (flushed) { + return; + } + try { + byte[] finalBytes = lastRawDataChunk == null + ? encryptingCipher.doFinal() + : encryptingCipher.doFinal(lastRawDataChunk, 0, lastRawDataChunk.length); + final int authTagLengthBits = 128; + if (authTagProducer != null) { + authTagProducer.update(finalBytes, 0, finalBytes.length); + encodeAndWrite(finalBytes, 0, finalBytes.length, true); + } else { + encodeAndWrite(finalBytes, 0, finalBytes.length - authTagLengthBits / 8, true); + } + out.write(new byte[]{'.'}); + + if (authTagProducer == null) { + encodeAndWrite(finalBytes, finalBytes.length - authTagLengthBits / 8, authTagLengthBits / 8, true); + } else { + byte[] authTag = authTagProducer.getTag(); + encodeAndWrite(authTag, 0, authTagLengthBits / 8, true); + } + } catch (Exception ex) { + throw new SecurityException(); + } + flushed = true; + } + private byte[] newArray(byte[] src, int srcPos, int srcLen) { + byte[] buf = new byte[srcLen]; + System.arraycopy(src, srcPos, buf, 0, srcLen); + return buf; + } + private byte[] newArray(byte[] src, int srcPos, int srcLen, byte[] src2, int srcPos2, int srcLen2) { + byte[] buf = new byte[srcLen + srcLen2]; + System.arraycopy(src, srcPos, buf, 0, srcLen); + System.arraycopy(src2, srcPos2, buf, srcLen, srcLen2); + return buf; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java new file mode 100644 index 0000000..483ff52 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/JweUtils.java @@ -0,0 +1,97 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import javax.crypto.SecretKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; +import org.apache.cxf.rs.security.jose.jwk.JwkUtils; + +public final class JweUtils { + private JweUtils() { + + } + public static KeyEncryptionAlgorithm getKeyEncryptionAlgorithm(JsonWebKey jwk) { + return getKeyEncryptionAlgorithm(jwk, null); + } + public static KeyEncryptionAlgorithm getKeyEncryptionAlgorithm(JsonWebKey jwk, String defaultAlgorithm) { + String keyEncryptionAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm(); + KeyEncryptionAlgorithm keyEncryptionProvider = null; + if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) { + keyEncryptionProvider = new RSAOaepKeyEncryptionAlgorithm(JwkUtils.toRSAPublicKey(jwk), + keyEncryptionAlgo); + } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) { + SecretKey key = JwkUtils.toSecretKey(jwk); + if (Algorithm.isAesKeyWrap(keyEncryptionAlgo)) { + keyEncryptionProvider = new AesWrapKeyEncryptionAlgorithm(key, keyEncryptionAlgo); + } else if (Algorithm.isAesGcmKeyWrap(keyEncryptionAlgo)) { + keyEncryptionProvider = new AesGcmWrapKeyEncryptionAlgorithm(key, keyEncryptionAlgo); + } + } else { + // TODO: support elliptic curve keys + } + return keyEncryptionProvider; + } + public static KeyDecryptionAlgorithm getKeyDecryptionAlgorithm(JsonWebKey jwk) { + return getKeyDecryptionAlgorithm(jwk, null); + } + public static KeyDecryptionAlgorithm getKeyDecryptionAlgorithm(JsonWebKey jwk, String defaultAlgorithm) { + String keyEncryptionAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm(); + KeyDecryptionAlgorithm keyDecryptionProvider = null; + if (JsonWebKey.KEY_TYPE_RSA.equals(jwk.getKeyType())) { + keyDecryptionProvider = new RSAOaepKeyDecryptionAlgorithm(JwkUtils.toRSAPrivateKey(jwk), + keyEncryptionAlgo); + } else if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) { + SecretKey key = JwkUtils.toSecretKey(jwk); + if (Algorithm.isAesKeyWrap(jwk.getAlgorithm())) { + keyDecryptionProvider = new AesWrapKeyDecryptionAlgorithm(key, keyEncryptionAlgo); + } else if (Algorithm.isAesGcmKeyWrap(jwk.getAlgorithm())) { + keyDecryptionProvider = new AesGcmWrapKeyDecryptionAlgorithm(key, keyEncryptionAlgo); + } + } else { + // TODO: support elliptic curve keys + } + return keyDecryptionProvider; + } + public static ContentEncryptionAlgorithm getContentEncryptionAlgorithm(JsonWebKey jwk) { + return getContentEncryptionAlgorithm(jwk, null); + } + public static ContentEncryptionAlgorithm getContentEncryptionAlgorithm(JsonWebKey jwk, String defaultAlgorithm) { + String ctEncryptionAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm(); + ContentEncryptionAlgorithm contentEncryptionProvider = null; + if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) { + SecretKey key = JwkUtils.toSecretKey(jwk); + if (Algorithm.isAesGcm(ctEncryptionAlgo)) { + contentEncryptionProvider = new AesGcmContentEncryptionAlgorithm(key, null, ctEncryptionAlgo); + } + } + return contentEncryptionProvider; + } + public static SecretKey getContentDecryptionSecretKey(JsonWebKey jwk) { + return getContentDecryptionSecretKey(jwk, null); + } + public static SecretKey getContentDecryptionSecretKey(JsonWebKey jwk, String defaultAlgorithm) { + String ctEncryptionAlgo = jwk.getAlgorithm() == null ? defaultAlgorithm : jwk.getAlgorithm(); + if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType()) && Algorithm.isAesGcm(ctEncryptionAlgo)) { + return JwkUtils.toSecretKey(jwk); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java new file mode 100644 index 0000000..9932ab2 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyDecryptionAlgorithm.java @@ -0,0 +1,24 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + +public interface KeyDecryptionAlgorithm { + byte[] getDecryptedContentEncryptionKey(JweCompactConsumer consumer); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionAlgorithm.java new file mode 100644 index 0000000..3885291 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/KeyEncryptionAlgorithm.java @@ -0,0 +1,25 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + + +public interface KeyEncryptionAlgorithm { + String getAlgorithm(); + byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..d338cdd --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyDecryptionAlgorithm.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import org.apache.cxf.common.util.Base64UrlUtility; + +public class PbesHmacAesWrapKeyDecryptionAlgorithm implements KeyDecryptionAlgorithm { + private byte[] password; + public PbesHmacAesWrapKeyDecryptionAlgorithm(String password) { + this(PbesHmacAesWrapKeyEncryptionAlgorithm.stringToBytes(password)); + } + public PbesHmacAesWrapKeyDecryptionAlgorithm(char[] password) { + this(PbesHmacAesWrapKeyEncryptionAlgorithm.charsToBytes(password)); + } + public PbesHmacAesWrapKeyDecryptionAlgorithm(byte[] password) { + this.password = password; + } + @Override + public byte[] getDecryptedContentEncryptionKey(JweCompactConsumer consumer) { + byte[] saltInput = getDecodedBytes(consumer, "p2s"); + int pbesCount = consumer.getJweHeaders().getIntegerHeader("p2c"); + String keyAlgoJwt = consumer.getJweHeaders().getAlgorithm(); + int keySize = PbesHmacAesWrapKeyEncryptionAlgorithm.getKeySize(keyAlgoJwt); + byte[] derivedKey = PbesHmacAesWrapKeyEncryptionAlgorithm + .createDerivedKey(keyAlgoJwt, keySize, password, saltInput, pbesCount); + KeyDecryptionAlgorithm aesWrap = new AesWrapKeyDecryptionAlgorithm(derivedKey); + return aesWrap.getDecryptedContentEncryptionKey(consumer); + } + private byte[] getDecodedBytes(JweCompactConsumer consumer, String headerName) { + try { + Object headerValue = consumer.getJweHeaders().getHeader(headerName); + return Base64UrlUtility.decode(headerValue.toString()); + } catch (Exception ex) { + throw new SecurityException(ex); + } + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..4697cad --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/PbesHmacAesWrapKeyEncryptionAlgorithm.java @@ -0,0 +1,173 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.common.util.crypto.CryptoUtils; +import org.apache.cxf.rs.security.jose.jwa.Algorithm; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.digests.SHA384Digest; +import org.bouncycastle.crypto.digests.SHA512Digest; +import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; + +public class PbesHmacAesWrapKeyEncryptionAlgorithm implements KeyEncryptionAlgorithm { + private static final Set SUPPORTED_ALGORITHMS = new HashSet( + Arrays.asList(Algorithm.PBES2_HS256_A128KW.getJwtName(), + Algorithm.PBES2_HS384_A192KW.getJwtName(), + Algorithm.PBES2_HS512_A256KW.getJwtName())); + private static final Map PBES_HMAC_MAP; + private static final Map PBES_AES_MAP; + private static final Map DERIVED_KEY_SIZE_MAP; + static { + PBES_HMAC_MAP = new HashMap(); + PBES_HMAC_MAP.put(Algorithm.PBES2_HS256_A128KW.getJwtName(), 256); + PBES_HMAC_MAP.put(Algorithm.PBES2_HS384_A192KW.getJwtName(), 384); + PBES_HMAC_MAP.put(Algorithm.PBES2_HS512_A256KW.getJwtName(), 512); + + PBES_AES_MAP = new HashMap(); + PBES_AES_MAP.put(Algorithm.PBES2_HS256_A128KW.getJwtName(), Algorithm.A128KW.getJwtName()); + PBES_AES_MAP.put(Algorithm.PBES2_HS384_A192KW.getJwtName(), Algorithm.A192KW.getJwtName()); + PBES_AES_MAP.put(Algorithm.PBES2_HS512_A256KW.getJwtName(), Algorithm.A256KW.getJwtName()); + + DERIVED_KEY_SIZE_MAP = new HashMap(); + DERIVED_KEY_SIZE_MAP.put(Algorithm.PBES2_HS256_A128KW.getJwtName(), 16); + DERIVED_KEY_SIZE_MAP.put(Algorithm.PBES2_HS384_A192KW.getJwtName(), 24); + DERIVED_KEY_SIZE_MAP.put(Algorithm.PBES2_HS512_A256KW.getJwtName(), 32); + } + + + private byte[] password; + private int pbesCount; + private String keyAlgoJwt; + public PbesHmacAesWrapKeyEncryptionAlgorithm(String password, String keyAlgoJwt) { + this(stringToBytes(password), keyAlgoJwt); + } + public PbesHmacAesWrapKeyEncryptionAlgorithm(String password, int pbesCount, String keyAlgoJwt) { + this(stringToBytes(password), pbesCount, keyAlgoJwt); + } + public PbesHmacAesWrapKeyEncryptionAlgorithm(char[] password, String keyAlgoJwt) { + this(password, 4096, keyAlgoJwt); + } + public PbesHmacAesWrapKeyEncryptionAlgorithm(char[] password, int pbesCount, String keyAlgoJwt) { + this(charsToBytes(password), pbesCount, keyAlgoJwt); + } + public PbesHmacAesWrapKeyEncryptionAlgorithm(byte[] password, String keyAlgoJwt) { + this(password, 4096, keyAlgoJwt); + } + public PbesHmacAesWrapKeyEncryptionAlgorithm(byte[] password, int pbesCount, String keyAlgoJwt) { + this.password = password; + this.keyAlgoJwt = validateKeyAlgorithm(keyAlgoJwt); + this.pbesCount = validatePbesCount(pbesCount); + } + + @Override + public byte[] getEncryptedContentEncryptionKey(JweHeaders headers, byte[] cek) { + int keySize = getKeySize(keyAlgoJwt); + byte[] saltInput = CryptoUtils.generateSecureRandomBytes(keySize); + byte[] derivedKey = createDerivedKey(keyAlgoJwt, keySize, password, saltInput, pbesCount); + + headers.setHeader("p2s", Base64UrlUtility.encode(saltInput)); + headers.setIntegerHeader("p2c", pbesCount); + + final String aesAlgoJwt = PBES_AES_MAP.get(keyAlgoJwt); + KeyEncryptionAlgorithm aesWrap = new AesWrapKeyEncryptionAlgorithm(derivedKey, aesAlgoJwt) { + protected void checkAlgorithms(JweHeaders headers) { + // complete + } + protected String getKeyEncryptionAlgoJava(JweHeaders headers) { + return Algorithm.AES_WRAP_ALGO_JAVA; + } + }; + return aesWrap.getEncryptedContentEncryptionKey(headers, cek); + + + } + static int getKeySize(String keyAlgoJwt) { + return DERIVED_KEY_SIZE_MAP.get(keyAlgoJwt); + } + static byte[] createDerivedKey(String keyAlgoJwt, int keySize, + byte[] password, byte[] saltInput, int pbesCount) { + byte[] saltValue = createSaltValue(keyAlgoJwt, saltInput); + Digest digest = null; + int macSigSize = PBES_HMAC_MAP.get(keyAlgoJwt); + if (macSigSize == 256) { + digest = new SHA256Digest(); + } else if (macSigSize == 384) { + digest = new SHA384Digest(); + } else { + digest = new SHA512Digest(); + } + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(digest); + gen.init(password, saltValue, pbesCount); + return ((KeyParameter) gen.generateDerivedParameters(keySize * 8)).getKey(); + } + + + private static byte[] createSaltValue(String keyAlgoJwt, byte[] saltInput) { + byte[] algoBytes = stringToBytes(keyAlgoJwt); + byte[] saltValue = new byte[algoBytes.length + 1 + saltInput.length]; + System.arraycopy(algoBytes, 0, saltValue, 0, algoBytes.length); + saltValue[algoBytes.length] = 0; + System.arraycopy(saltInput, 0, saltValue, algoBytes.length + 1, saltInput.length); + return saltValue; + } + static String validateKeyAlgorithm(String algo) { + if (!SUPPORTED_ALGORITHMS.contains(algo)) { + throw new SecurityException(); + } + return algo; + } + static int validatePbesCount(int count) { + if (count < 1000) { + throw new SecurityException(); + } + return count; + } + + static byte[] stringToBytes(String str) { + try { + return str.getBytes("UTF-8"); + } catch (UnsupportedEncodingException ex) { + throw new SecurityException(ex); + } + } + static byte[] charsToBytes(char[] chars) { + ByteBuffer bb = Charset.forName("UTF-8").encode(CharBuffer.wrap(chars)); + byte[] b = new byte[bb.remaining()]; + bb.get(b); + return b; + } + @Override + public String getAlgorithm() { + return keyAlgoJwt; + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..a0ea63d --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyDecryptionAlgorithm.java @@ -0,0 +1,45 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.security.interfaces.RSAPrivateKey; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; + +public class RSAOaepKeyDecryptionAlgorithm extends WrappedKeyDecryptionAlgorithm { + public RSAOaepKeyDecryptionAlgorithm(RSAPrivateKey privateKey) { + this(privateKey, null); + } + public RSAOaepKeyDecryptionAlgorithm(RSAPrivateKey privateKey, String supportedAlgo) { + this(privateKey, supportedAlgo, true); + } + public RSAOaepKeyDecryptionAlgorithm(RSAPrivateKey privateKey, String supportedAlgo, boolean unwrap) { + super(privateKey, supportedAlgo, unwrap); + } + protected int getKeyCipherBlockSize() { + return ((RSAPrivateKey)getCekDecryptionKey()).getModulus().toByteArray().length; + } + @Override + protected void validateKeyEncryptionAlgorithm(String keyAlgo) { + super.validateKeyEncryptionAlgorithm(keyAlgo); + if (!Algorithm.isRsaOaep(keyAlgo)) { + throw new SecurityException(); + } + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java new file mode 100644 index 0000000..b658e36 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/RSAOaepKeyEncryptionAlgorithm.java @@ -0,0 +1,39 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.security.interfaces.RSAPublicKey; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.apache.cxf.rs.security.jose.jwa.Algorithm; + +public class RSAOaepKeyEncryptionAlgorithm extends AbstractWrapKeyEncryptionAlgorithm { + private static final Set SUPPORTED_ALGORITHMS = new HashSet( + Arrays.asList(Algorithm.RSA_OAEP.getJwtName(), + Algorithm.RSA_OAEP_256.getJwtName())); + public RSAOaepKeyEncryptionAlgorithm(RSAPublicKey publicKey, String jweAlgo) { + this(publicKey, jweAlgo, true); + } + public RSAOaepKeyEncryptionAlgorithm(RSAPublicKey publicKey, String jweAlgo, boolean wrap) { + super(publicKey, jweAlgo, wrap, SUPPORTED_ALGORITHMS); + } + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java new file mode 100644 index 0000000..8af2c63 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyDecryptionAlgorithm.java @@ -0,0 +1,85 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import java.security.Key; +import java.security.spec.AlgorithmParameterSpec; + +import org.apache.cxf.common.util.crypto.CryptoUtils; +import org.apache.cxf.common.util.crypto.KeyProperties; +import org.apache.cxf.rs.security.jose.jwa.Algorithm; + +public class WrappedKeyDecryptionAlgorithm implements KeyDecryptionAlgorithm { + private Key cekDecryptionKey; + private boolean unwrap; + private String supportedAlgo; + public WrappedKeyDecryptionAlgorithm(Key cekDecryptionKey) { + this(cekDecryptionKey, null); + } + public WrappedKeyDecryptionAlgorithm(Key cekDecryptionKey, String supportedAlgo) { + this(cekDecryptionKey, supportedAlgo, true); + } + public WrappedKeyDecryptionAlgorithm(Key cekDecryptionKey, String supportedAlgo, boolean unwrap) { + this.cekDecryptionKey = cekDecryptionKey; + this.supportedAlgo = supportedAlgo; + this.unwrap = unwrap; + } + public byte[] getDecryptedContentEncryptionKey(JweCompactConsumer consumer) { + KeyProperties keyProps = new KeyProperties(getKeyEncryptionAlgorithm(consumer)); + AlgorithmParameterSpec spec = getAlgorithmParameterSpec(consumer); + if (spec != null) { + keyProps.setAlgoSpec(spec); + } + if (!unwrap) { + keyProps.setBlockSize(getKeyCipherBlockSize()); + return CryptoUtils.decryptBytes(getEncryptedContentEncryptionKey(consumer), + getCekDecryptionKey(), keyProps); + } else { + return CryptoUtils.unwrapSecretKey(getEncryptedContentEncryptionKey(consumer), + getContentEncryptionAlgorithm(consumer), + getCekDecryptionKey(), + keyProps).getEncoded(); + } + } + + protected Key getCekDecryptionKey() { + return cekDecryptionKey; + } + protected int getKeyCipherBlockSize() { + return -1; + } + protected String getKeyEncryptionAlgorithm(JweCompactConsumer consumer) { + String keyAlgo = consumer.getJweHeaders().getKeyEncryptionAlgorithm(); + return Algorithm.toJavaName(keyAlgo); + } + protected void validateKeyEncryptionAlgorithm(String keyAlgo) { + if (keyAlgo == null || supportedAlgo != null && supportedAlgo.equals(keyAlgo)) { + throw new SecurityException(); + } + } + protected String getContentEncryptionAlgorithm(JweCompactConsumer consumer) { + return Algorithm.toJavaName(consumer.getJweHeaders().getContentEncryptionAlgorithm()); + } + protected AlgorithmParameterSpec getAlgorithmParameterSpec(JweCompactConsumer consumer) { + return null; + } + protected byte[] getEncryptedContentEncryptionKey(JweCompactConsumer consumer) { + return consumer.getEncryptedContentEncryptionKey(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java new file mode 100644 index 0000000..c74e880 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweDecryption.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import org.apache.cxf.rs.security.jose.JoseHeadersReader; + +public class WrappedKeyJweDecryption extends AbstractJweDecryption { + + public WrappedKeyJweDecryption(KeyDecryptionAlgorithm keyDecryptionAlgo, + ContentDecryptionAlgorithm contentDecryptionAlgo) { + this(keyDecryptionAlgo, null, contentDecryptionAlgo); + } + public WrappedKeyJweDecryption(KeyDecryptionAlgorithm keyDecryptionAlgo, + JoseHeadersReader reader, + ContentDecryptionAlgorithm cipherProps) { + super(reader, keyDecryptionAlgo, cipherProps); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweEncryption.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweEncryption.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweEncryption.java new file mode 100644 index 0000000..446a675 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwe/WrappedKeyJweEncryption.java @@ -0,0 +1,47 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwe; + +import org.apache.cxf.rs.security.jose.JoseHeadersWriter; + +public class WrappedKeyJweEncryption extends AbstractJweEncryption { + public WrappedKeyJweEncryption(KeyEncryptionAlgorithm keyEncryptionAlgorithm, + ContentEncryptionAlgorithm contentEncryptionAlgo) { + this(keyEncryptionAlgorithm, contentEncryptionAlgo, null); + } + public WrappedKeyJweEncryption(KeyEncryptionAlgorithm keyEncryptionAlgorithm, + ContentEncryptionAlgorithm contentEncryptionAlgo, + JoseHeadersWriter writer) { + this(new JweHeaders(keyEncryptionAlgorithm.getAlgorithm(), contentEncryptionAlgo.getAlgorithm()), + keyEncryptionAlgorithm, contentEncryptionAlgo, writer); + } + public WrappedKeyJweEncryption(JweHeaders headers, + KeyEncryptionAlgorithm keyEncryptionAlgorithm, + ContentEncryptionAlgorithm contentEncryptionAlgo) { + this(headers, keyEncryptionAlgorithm, contentEncryptionAlgo, null); + } + public WrappedKeyJweEncryption(JweHeaders headers, + KeyEncryptionAlgorithm keyEncryptionAlgorithm, + ContentEncryptionAlgorithm contentEncryptionAlgo, + JoseHeadersWriter writer) { + super(headers, contentEncryptionAlgo, keyEncryptionAlgorithm, writer); + } + + +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java new file mode 100644 index 0000000..fa4f8ba --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/DefaultJwkReaderWriter.java @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwk; + +import org.apache.cxf.rs.security.jose.AbstractJoseObjectReaderWriter; + + + + +public class DefaultJwkReaderWriter extends AbstractJoseObjectReaderWriter + implements JwkReaderWriter { + @Override + public String jwkSetToJson(JsonWebKeys jwks) { + return toJson(jwks); + } + @Override + public JsonWebKeys jsonToJwkSet(String jwksJson) { + JsonWebKeys jwks = new JsonWebKeys(); + fromJsonInternal(jwks, jwksJson); + return jwks; + } + @Override + public String jwkToJson(JsonWebKey jwk) { + return toJson(jwk); + } + @Override + public JsonWebKey jsonToJwk(String jwkJson) { + JsonWebKey jwk = new JsonWebKey(); + fromJsonInternal(jwk, jwkJson); + return jwk; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/9c053334/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java new file mode 100644 index 0000000..ef594e6 --- /dev/null +++ b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jwk/JsonWebKey.java @@ -0,0 +1,160 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.rs.security.jose.jwk; + +import java.util.List; +import java.util.Map; + +import org.apache.cxf.helpers.CastUtils; +import org.apache.cxf.rs.security.jose.AbstractJoseObject; +import org.apache.cxf.rs.security.jose.JoseConstants; + + +public class JsonWebKey extends AbstractJoseObject { + + public static final String KEY_TYPE = "kty"; + public static final String PUBLIC_KEY_USE = "use"; + public static final String KEY_OPERATIONS = "key_ops"; + public static final String KEY_ALGO = JoseConstants.HEADER_ALGORITHM; + public static final String KEY_ID = JoseConstants.HEADER_KEY_ID; + public static final String X509_URL = JoseConstants.HEADER_X509_URL; + public static final String X509_CHAIN = JoseConstants.HEADER_X509_CHAIN; + public static final String X509_THUMBPRINT = JoseConstants.HEADER_X509_THUMBPRINT; + public static final String X509_THUMBPRINT_SHA256 = JoseConstants.HEADER_X509_THUMBPRINT_SHA256; + + public static final String KEY_TYPE_RSA = "RSA"; + public static final String RSA_MODULUS = "n"; + public static final String RSA_PUBLIC_EXP = "e"; + public static final String RSA_PRIVATE_EXP = "d"; + public static final String RSA_FIRST_PRIME_FACTOR = "p"; + public static final String RSA_SECOND_PRIME_FACTOR = "q"; + public static final String RSA_FIRST_PRIME_CRT = "dp"; + public static final String RSA_SECOND_PRIME_CRT = "dq"; + public static final String RSA_FIRST_CRT_COEFFICIENT = "qi"; + + public static final String KEY_TYPE_OCTET = "oct"; + public static final String OCTET_KEY_VALUE = "k"; + + public static final String KEY_TYPE_ELLIPTIC = "EC"; + public static final String EC_CURVE = "crv"; + public static final String EC_CURVE_P256 = "P-256"; + public static final String EC_CURVE_P384 = "P-384"; + public static final String EC_CURVE_P512 = "P-512"; + public static final String EC_X_COORDINATE = "x"; + public static final String EC_Y_COORDINATE = "y"; + public static final String EC_PRIVATE_KEY = "d"; + + public static final String PUBLIC_KEY_USE_SIGN = "sig"; + public static final String PUBLIC_KEY_USE_ENCRYPT = "enc"; + + public static final String KEY_OPER_SIGN = "sign"; + public static final String KEY_OPER_VERIFY = "verify"; + public static final String KEY_OPER_ENCRYPT = "encrypt"; + public static final String KEY_OPER_DECRYPT = "decrypt"; + + public JsonWebKey() { + + } + + public JsonWebKey(Map values) { + super(values); + } + + public void setKeyType(String keyType) { + super.setValue(KEY_TYPE, keyType); + } + + public String getKeyType() { + return (String)super.getValue(KEY_TYPE); + } + + public void setPublicKeyUse(String use) { + super.setValue(PUBLIC_KEY_USE, use); + } + + public String getPublicKeyUse() { + return (String)super.getValue(PUBLIC_KEY_USE); + } + + public void setKeyOperation(List keyOperation) { + super.setValue(KEY_OPERATIONS, keyOperation); + } + + public List getKeyOperation() { + return CastUtils.cast((List)super.getValue(KEY_OPERATIONS)); + } + + public void setAlgorithm(String algorithm) { + super.setValue(KEY_ALGO, algorithm); + } + + public String getAlgorithm() { + return (String)super.getValue(KEY_ALGO); + } + + public void setKid(String kid) { + super.setValue(KEY_ID, kid); + } + + public String getKid() { + return (String)super.getValue(KEY_ID); + } + + public void setX509Url(String x509Url) { + super.setValue(X509_URL, x509Url); + } + + public String getX509Url() { + return (String)super.getValue(X509_URL); + } + + public void setX509Chain(String x509Chain) { + super.setValue(X509_CHAIN, x509Chain); + } + + public String getX509Chain() { + return (String)super.getValue(X509_CHAIN); + } + + public void setX509Thumbprint(String x509Thumbprint) { + super.setValue(X509_THUMBPRINT, x509Thumbprint); + } + + public String getX509Thumbprint() { + return (String)super.getValue(X509_THUMBPRINT); + } + + public void setX509ThumbprintSHA256(String x509Thumbprint) { + super.setValue(X509_THUMBPRINT_SHA256, x509Thumbprint); + } + + public String getX509ThumbprintSHA256() { + return (String)super.getValue(X509_THUMBPRINT_SHA256); + } + + public JsonWebKey setProperty(String name, Object value) { + super.setValue(name, value); + return this; + } + + public Object getProperty(String name) { + return super.getValue(name); + } + +}