001package org.hl7.fhir.r4.utils; 002 003import java.io.ByteArrayInputStream; 004import java.io.FileOutputStream; 005import java.io.IOException; 006import java.io.OutputStream; 007import java.nio.file.Files; 008import java.nio.file.Paths; 009import java.security.InvalidAlgorithmParameterException; 010import java.security.KeyException; 011import java.security.KeyFactory; 012import java.security.KeyPair; 013import java.security.KeyPairGenerator; 014import java.security.NoSuchAlgorithmException; 015import java.security.PrivateKey; 016import java.security.PublicKey; 017import java.security.spec.PKCS8EncodedKeySpec; 018import java.security.spec.X509EncodedKeySpec; 019import java.util.Collections; 020 021import javax.xml.crypto.MarshalException; 022import javax.xml.crypto.dsig.CanonicalizationMethod; 023import javax.xml.crypto.dsig.DigestMethod; 024import javax.xml.crypto.dsig.Reference; 025import javax.xml.crypto.dsig.SignatureMethod; 026import javax.xml.crypto.dsig.SignedInfo; 027import javax.xml.crypto.dsig.Transform; 028import javax.xml.crypto.dsig.XMLSignature; 029import javax.xml.crypto.dsig.XMLSignatureException; 030import javax.xml.crypto.dsig.XMLSignatureFactory; 031import javax.xml.crypto.dsig.dom.DOMSignContext; 032import javax.xml.crypto.dsig.keyinfo.KeyInfo; 033import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; 034import javax.xml.crypto.dsig.keyinfo.KeyValue; 035import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; 036import javax.xml.crypto.dsig.spec.TransformParameterSpec; 037import javax.xml.parsers.DocumentBuilder; 038import javax.xml.parsers.DocumentBuilderFactory; 039import javax.xml.parsers.ParserConfigurationException; 040 041import org.hl7.fhir.exceptions.FHIRException; 042import org.hl7.fhir.utilities.xml.XmlGenerator; 043import org.w3c.dom.Document; 044import org.xml.sax.SAXException; 045 046public class DigitalSignatures { 047 048 public static PrivateKey getPrivateKey(String filename) throws Exception { 049 050 byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); 051 052 PKCS8EncodedKeySpec spec = 053 new PKCS8EncodedKeySpec(keyBytes); 054 KeyFactory kf = KeyFactory.getInstance("RSA"); 055 return kf.generatePrivate(spec); 056 } 057 058 public static PublicKey getPublicKey(String filename) throws Exception { 059 060 byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); 061 062 X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); 063 KeyFactory kf = KeyFactory.getInstance("RSA"); 064 return kf.generatePublic(spec); 065 } 066 067 public static void main(String[] args) throws Exception { 068 // http://docs.oracle.com/javase/7/docs/technotes/guides/security/xmldsig/XMLDigitalSignature.html 069 // 070 byte[] inputXml = "<Envelope xmlns=\"urn:envelope\">\r\n</Envelope>\r\n".getBytes(); 071 // load the document that's going to be signed 072 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 073 dbf.setNamespaceAware(true); 074 DocumentBuilder builder = dbf.newDocumentBuilder(); 075 Document doc = builder.parse(new ByteArrayInputStream(inputXml)); 076 077// // create a key pair 078// KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 079// kpg.initialize(512); 080// KeyPair kp = kpg.generateKeyPair(); 081 PublicKey pub = getPublicKey("C:\\work\\fhirserver\\tests\\signatures\\public_key.der"); 082 PrivateKey priv = getPrivateKey("C:\\work\\fhirserver\\tests\\signatures\\private_key.der"); 083 084 // sign the document 085 DOMSignContext dsc = new DOMSignContext(priv, doc.getDocumentElement()); 086 XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); 087 088 Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null), Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, null); 089 SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref)); 090 091 KeyInfoFactory kif = fac.getKeyInfoFactory(); 092 KeyValue kv = kif.newKeyValue(pub); 093 KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv)); 094 XMLSignature signature = fac.newXMLSignature(si, ki); 095 signature.sign(dsc); 096 097 OutputStream os = new FileOutputStream("c:\\temp\\java-digsig.xml"); 098 new XmlGenerator().generate(doc.getDocumentElement(), os); 099 } 100}