001package org.hl7.fhir.r4.utils;
002
003/*-
004 * #%L
005 * org.hl7.fhir.r4
006 * %%
007 * Copyright (C) 2014 - 2019 Health Level 7
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023
024import java.io.ByteArrayInputStream;
025import java.io.FileOutputStream;
026import java.io.OutputStream;
027import java.nio.file.Files;
028import java.nio.file.Paths;
029import java.security.KeyFactory;
030import java.security.PrivateKey;
031import java.security.PublicKey;
032import java.security.spec.PKCS8EncodedKeySpec;
033import java.security.spec.X509EncodedKeySpec;
034import java.util.Collections;
035
036import javax.xml.crypto.dsig.CanonicalizationMethod;
037import javax.xml.crypto.dsig.DigestMethod;
038import javax.xml.crypto.dsig.Reference;
039import javax.xml.crypto.dsig.SignatureMethod;
040import javax.xml.crypto.dsig.SignedInfo;
041import javax.xml.crypto.dsig.Transform;
042import javax.xml.crypto.dsig.XMLSignature;
043import javax.xml.crypto.dsig.XMLSignatureFactory;
044import javax.xml.crypto.dsig.dom.DOMSignContext;
045import javax.xml.crypto.dsig.keyinfo.KeyInfo;
046import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
047import javax.xml.crypto.dsig.keyinfo.KeyValue;
048import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
049import javax.xml.crypto.dsig.spec.TransformParameterSpec;
050import javax.xml.parsers.DocumentBuilder;
051import javax.xml.parsers.DocumentBuilderFactory;
052
053import org.hl7.fhir.utilities.xml.XmlGenerator;
054import org.w3c.dom.Document;
055
056public class DigitalSignatures {
057
058  public static PrivateKey getPrivateKey(String filename) throws Exception {
059
060    byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
061
062    PKCS8EncodedKeySpec spec =
063        new PKCS8EncodedKeySpec(keyBytes);
064    KeyFactory kf = KeyFactory.getInstance("RSA");
065    return kf.generatePrivate(spec);
066  }
067
068  public static PublicKey getPublicKey(String filename) throws Exception {
069
070    byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
071
072    X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
073    KeyFactory kf = KeyFactory.getInstance("RSA");
074    return kf.generatePublic(spec);
075  }
076
077  public static void main(String[] args) throws Exception {
078    // http://docs.oracle.com/javase/7/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html
079    //
080    byte[] inputXml = "<Envelope xmlns=\"urn:envelope\">\r\n</Envelope>\r\n".getBytes();
081    // load the document that's going to be signed
082    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
083    dbf.setNamespaceAware(true);
084    DocumentBuilder builder = dbf.newDocumentBuilder();  
085    Document doc = builder.parse(new ByteArrayInputStream(inputXml)); 
086    
087//    // create a key pair
088//    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
089//    kpg.initialize(512);
090//    KeyPair kp = kpg.generateKeyPair(); 
091    PublicKey pub = getPublicKey("C:\\work\\fhirserver\\tests\\signatures\\public_key.der");
092    PrivateKey priv = getPrivateKey("C:\\work\\fhirserver\\tests\\signatures\\private_key.der");
093    
094    // sign the document
095    DOMSignContext dsc = new DOMSignContext(priv, doc.getDocumentElement()); 
096    XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); 
097   
098    Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null), Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, null);
099    SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref));
100    
101    KeyInfoFactory kif = fac.getKeyInfoFactory(); 
102    KeyValue kv = kif.newKeyValue(pub);
103    KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
104    XMLSignature signature = fac.newXMLSignature(si, ki); 
105    signature.sign(dsc);
106    
107    OutputStream os = new FileOutputStream("c:\\temp\\java-digsig.xml");
108    new XmlGenerator().generate(doc.getDocumentElement(), os);
109  }
110}