/** * 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.jws; import java.security.PrivateKey; import java.util.Properties; import org.apache.cxf.common.util.Base64UrlUtility; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; import org.apache.cxf.message.Message; import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm; import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; public class JwsCompactProducer { private JsonMapObjectReaderWriter writer = new JsonMapObjectReaderWriter(); private JwsHeaders headers; private String plainJwsPayload; private String signature; private boolean detached; public JwsCompactProducer(String plainJwsPayload) { this(plainJwsPayload, false); } public JwsCompactProducer(String plainJwsPayload, boolean detached) { this(null, null, plainJwsPayload, detached); } public JwsCompactProducer(JwsHeaders headers, String plainJwsPayload) { this(headers, plainJwsPayload, false); } public JwsCompactProducer(JwsHeaders headers, String plainJwsPayload, boolean detached) { this(headers, null, plainJwsPayload, detached); } protected JwsCompactProducer(JwsHeaders headers, JsonMapObjectReaderWriter w, String plainJwsPayload) { this(headers, w, plainJwsPayload, false); } protected JwsCompactProducer(JwsHeaders headers, JsonMapObjectReaderWriter w, String plainJwsPayload, boolean detached) { this.headers = headers; if (w != null) { this.writer = w; } this.plainJwsPayload = plainJwsPayload; this.detached = detached; } public JwsHeaders getJwsHeaders() { if (headers == null) { headers = new JwsHeaders(); } return headers; } public String getUnsignedEncodedJws() { checkAlgorithm(); return Base64UrlUtility.encode(writer.toJson(getJwsHeaders())) + "." + (detached ? "" : Base64UrlUtility.encode(plainJwsPayload)); } private String getSigningInput() { checkAlgorithm(); boolean unencoded = JwsUtils.isPayloadUnencoded(getJwsHeaders()); return Base64UrlUtility.encode(writer.toJson(getJwsHeaders())) + "." + (unencoded ? plainJwsPayload : Base64UrlUtility.encode(plainJwsPayload)); } public String getEncodedSignature() { return signature; } public String getSignedEncodedJws() { checkAlgorithm(); boolean noSignature = StringUtils.isEmpty(signature); if (noSignature && !isPlainText()) { throw new IllegalStateException("Signature is not available"); } return getUnsignedEncodedJws() + "." + (noSignature ? "" : signature); } public String signWith(JsonWebKey jwk) { return signWith(JwsUtils.getSignatureProvider(jwk, headers.getSignatureAlgorithm())); } public String signWith(PrivateKey key) { return signWith(JwsUtils.getPrivateKeySignatureProvider(key, headers.getSignatureAlgorithm())); } public String signWith(byte[] key) { return signWith(JwsUtils.getHmacSignatureProvider(key, headers.getSignatureAlgorithm())); } public String signWith(JwsSignatureProvider signer) { if (headers.getSignatureAlgorithm() == null) { headers.setSignatureAlgorithm(signer.getAlgorithm()); } byte[] bytes = StringUtils.toBytesUTF8(getSigningInput()); byte[] sig = signer.sign(getJwsHeaders(), bytes); return setSignatureBytes(sig); } public String setSignatureText(String signatureText) { setEncodedSignature(Base64UrlUtility.encode(signatureText)); return getSignedEncodedJws(); } public boolean isPlainText() { return SignatureAlgorithm.NONE == getAlgorithm(); } public String setSignatureBytes(byte[] signatureOctets) { setEncodedSignature(Base64UrlUtility.encode(signatureOctets)); return getSignedEncodedJws(); } private void setEncodedSignature(String sig) { this.signature = sig; } private SignatureAlgorithm getAlgorithm() { return getJwsHeaders().getSignatureAlgorithm(); } private void checkAlgorithm() { if (getAlgorithm() == null) { Properties sigProps = JwsUtils.loadSignatureOutProperties(false); Message m = PhaseInterceptorChain.getCurrentMessage(); SignatureAlgorithm signatureAlgo = JwsUtils.getSignatureAlgorithm(m, sigProps, null, null); if (signatureAlgo != null) { getJwsHeaders().setSignatureAlgorithm(signatureAlgo); } } if (getAlgorithm() == null) { throw new JwsException(JwsException.Error.INVALID_ALGORITHM); } } }