blob: 440d9f634567ba2d5d4707ecf06fe43c6c11ab1e [file] [log] [blame]
/**
* 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.fediz.core.util;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.security.auth.DestroyFailedException;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import org.w3c.dom.Document;
import org.apache.wss4j.common.crypto.Crypto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class SignatureUtils {
private static final Logger LOG = LoggerFactory.getLogger(SignatureUtils.class);
private static final XMLSignatureFactory XML_SIGNATURE_FACTORY = XMLSignatureFactory.getInstance("DOM");
private SignatureUtils() {
}
public static Document signMetaInfo(Crypto crypto, String keyAlias, String keyPassword,
Document doc, String referenceID) throws Exception {
if (keyAlias == null || "".equals(keyAlias)) {
keyAlias = crypto.getDefaultX509Identifier();
}
X509Certificate cert = CertsUtils.getX509CertificateFromCrypto(crypto, keyAlias);
// }
/* public static ByteArrayOutputStream signMetaInfo(FederationContext config, InputStream metaInfo,
String referenceID)
throws Exception {
KeyManager keyManager = config.getSigningKey();
String keyAlias = keyManager.getKeyAlias();
String keypass = keyManager.getKeyPassword();
// in case we did not specify the key alias, we assume there is only one key in the keystore ,
// we use this key's alias as default.
if (keyAlias == null || "".equals(keyAlias)) {
//keyAlias = getDefaultX509Identifier(ks);
keyAlias = keyManager.getCrypto().getDefaultX509Identifier();
}
CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
cryptoType.setAlias(keyAlias);
X509Certificate[] issuerCerts = keyManager.getCrypto().getX509Certificates(cryptoType);
if (issuerCerts == null || issuerCerts.length == 0) {
throw new ProcessingException(
"No issuer certs were found to sign the metadata using issuer name: "
+ keyAlias);
}
X509Certificate cert = issuerCerts[0];
*/
final String signatureMethod;
if ("SHA1withDSA".equals(cert.getSigAlgName())) {
signatureMethod = SignatureMethod.DSA_SHA1;
} else if ("SHA1withRSA".equals(cert.getSigAlgName())) {
signatureMethod = SignatureMethod.RSA_SHA1;
} else if ("SHA256withRSA".equals(cert.getSigAlgName())) {
signatureMethod = SignatureMethod.RSA_SHA1;
} else {
LOG.error("Unsupported signature method: " + cert.getSigAlgName());
throw new RuntimeException("Unsupported signature method: " + cert.getSigAlgName());
}
List<Transform> transformList = new ArrayList<>();
transformList.add(XML_SIGNATURE_FACTORY.newTransform(Transform.ENVELOPED, (TransformParameterSpec)null));
transformList.add(XML_SIGNATURE_FACTORY.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE,
(C14NMethodParameterSpec)null));
// Create a Reference to the enveloped document (in this case,
// you are signing the whole document, so a URI of "" signifies
// that, and also specify the SHA1 digest algorithm and
// the ENVELOPED Transform.
Reference ref = XML_SIGNATURE_FACTORY.newReference(
"#" + referenceID,
XML_SIGNATURE_FACTORY.newDigestMethod(DigestMethod.SHA1, null),
transformList,
null, null);
// Create the SignedInfo.
SignedInfo si = XML_SIGNATURE_FACTORY.newSignedInfo(
XML_SIGNATURE_FACTORY.newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec)null),
XML_SIGNATURE_FACTORY.newSignatureMethod(
signatureMethod, null), Collections.singletonList(ref));
// step 2
// Load the KeyStore and get the signing key and certificate.
PrivateKey keyEntry = crypto.getPrivateKey(keyAlias, keyPassword);
// Create the KeyInfo containing the X509Data.
KeyInfoFactory kif = XML_SIGNATURE_FACTORY.getKeyInfoFactory();
List<Object> x509Content = new ArrayList<>();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(cert);
X509Data xd = kif.newX509Data(x509Content);
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
// step3
// Create a DOMSignContext and specify the RSA PrivateKey and
// location of the resulting XMLSignature's parent element.
//DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement());
DOMSignContext dsc = new DOMSignContext(keyEntry, doc.getDocumentElement());
dsc.setIdAttributeNS(doc.getDocumentElement(), null, "ID");
dsc.setNextSibling(doc.getDocumentElement().getFirstChild());
// Create the XMLSignature, but don't sign it yet.
XMLSignature signature = XML_SIGNATURE_FACTORY.newXMLSignature(si, ki);
// Marshal, generate, and sign the enveloped signature.
signature.sign(dsc);
// Clean the private key from memory when we're done
try {
keyEntry.destroy();
} catch (DestroyFailedException ex) {
// ignore
}
// step 4
// Output the resulting document.
return doc;
}
}