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}