Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.parelon.pskc; import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; import com.sun.org.apache.xml.internal.security.utils.Base64; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.util.ArrayList; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.security.auth.DestroyFailedException; import javax.swing.JOptionPane; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.codec.DecoderException; import org.w3c.dom.*; import org.xml.sax.SAXException; /** * Class that handles all the operation of both parsing, editing and creating * the PKCS XML file. * * @author Vincenzo Abate */ public class XmlManager { private String fileName = "", folderOut = "", manufactuer = "", issuer = "", preSharedKeyName = "PARELON ONLUS"; private String privateKeyFragment1 = "", privateKeyFragment2 = "", publicKey = ""; private CryptManager crypto; public XmlManager(String manufactuer, String issuer) { this.manufactuer = manufactuer; this.issuer = issuer; this.crypto = new CryptManager(); } private boolean validateSerial(String serialNo) { /** * validate the serial number: the serial must be formed by 9 integer * digits */ try { if (serialNo.length() != 9) { return false; } return (Long.parseLong(serialNo) > 0); } catch (NumberFormatException ex) { return false; } } public void convertXml(String fileIn, String fileOut) throws FileNotFoundException, SAXException, IOException, InvalidKeyException, Base64DecodingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, UnsupportedEncodingException, ParserConfigurationException, DecoderException, Exception { ArrayList<OtpSeed> seeds = new ArrayList<OtpSeed>(); /** * Parserizzazione XML */ FileInputStream fileToConvert = new FileInputStream(fileIn); DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document parsedXml = builder.parse(fileToConvert); fileToConvert.close(); if (parsedXml.hasChildNodes()) { int validSerials = 0; NodeList keyPackages = parsedXml.getElementsByTagName("KeyPackage"); for (int i = 0; i < keyPackages.getLength(); i++) { Node keyPackageNode = keyPackages.item(i); /** * Parse PSKC node structure */ String serialNo = ((Element) keyPackageNode).getElementsByTagName("SerialNo").item(0) .getTextContent(); if (validateSerial(serialNo)) { validSerials++; OtpSeed validSeed = new OtpSeed(); validSeed.setSerialNo(serialNo); validSeed.setCryptoId(String.format("KR-%06d", validSerials)); validSeed.setIssuer(issuer); validSeed.setKeyId(String.format("%08d", validSerials)); validSeed.setManufacturer(manufactuer); NodeList tempNode = ((Element) keyPackageNode).getElementsByTagName("xenc:CipherValue"); if (tempNode != null && tempNode.getLength() != 0) { validSeed.setCipherValue(((Element) tempNode.item(0)).getTextContent()); } seeds.add(validSeed); } } } /** * Creazione del nuovo XML */ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); // root elements Document doc = docBuilder.newDocument(); doc.setXmlVersion("1.0"); Element keyContainer = doc.createElement("KeyContainer"); doc.appendChild(keyContainer); keyContainer.setAttribute("xmlns", "urn:ietf:params:xml:ns:keyprov:pskc"); keyContainer.setAttribute("xmlns:ds", "http://www.w3.org/2000/09/xmldsig#"); keyContainer.setAttribute("xmlns:xenc", "http://www.w3.org/2001/04/xmlenc#"); keyContainer.setAttribute("Version", "1.0"); keyContainer.setAttribute("ID", "KC0001"); /** * Key Name */ Element encryptionKey = doc.createElement("EncryptionKey"); keyContainer.appendChild(encryptionKey); Element ds_keyName = doc.createElement("ds:KeyName"); encryptionKey.appendChild(ds_keyName); ds_keyName.setTextContent(this.preSharedKeyName); /** * MAC Method */ Element macMethod = doc.createElement("MACMethod"); keyContainer.appendChild(macMethod); macMethod.setAttribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#hmac-sha1"); /** * Mac Key */ Element macKey = doc.createElement("MACKey"); macMethod.appendChild(macKey); /** * EncryptionMethod */ Element encryptionMethod = doc.createElement("xenc:EncryptionMethod"); macKey.appendChild(encryptionMethod); encryptionMethod.setAttribute("Algorithm", "http://www.w3.org/2001/04/xmlenc#aes128-cbc"); /** * xenc:CipherData */ Element xenc_CipherData = doc.createElement("xenc:CipherData"); macKey.appendChild(xenc_CipherData); /** * xenc:CipherValue */ Element xenc_CipherValue = doc.createElement("xenc:CipherValue"); xenc_CipherData.appendChild(xenc_CipherValue); /** * Passo 1: Criptare la MAC Key */ String macSignature = Base64.encode(crypto.getAesCipheredMacKey()); xenc_CipherValue.setTextContent(macSignature); for (OtpSeed seed : seeds) { /** * Passo 2: Convertire il dato criptato */ byte[] reCipheredSecretBytes = crypto.convertRsaToAes(seed.getCipherValue()); seed.setCipherValue(Base64.encode(reCipheredSecretBytes)); /** * Passo 3: Firmare il dato criptato */ byte[] secretSignatureBytes = crypto.signCipheredSecret(reCipheredSecretBytes); seed.setValueMac(Base64.encode(secretSignatureBytes)); /** * KeyPackage */ Element keyPackageElement = doc.createElement("KeyPackage"); keyContainer.appendChild(keyPackageElement); /** * DeviceInfo */ Element deviceInfoElement = doc.createElement("DeviceInfo"); keyPackageElement.appendChild(deviceInfoElement); /** * Manufactuer */ Element manufactuerElement = doc.createElement("Manufactuer"); manufactuerElement.setTextContent(seed.getManufacturer()); deviceInfoElement.appendChild(manufactuerElement); /** * SerialNo */ Element serialNoElement = doc.createElement("SerialNo"); serialNoElement.setTextContent(seed.getSerialNo()); deviceInfoElement.appendChild(serialNoElement); /** * CryptoModuleInfo */ Element cryptoModuleInfoElement = doc.createElement("CryptoModuleInfo"); keyPackageElement.appendChild(cryptoModuleInfoElement); /** * ID */ Element idElement = doc.createElement("ID"); idElement.setTextContent(seed.getCryptoId()); cryptoModuleInfoElement.appendChild(idElement); /** * Key */ Element keyElement = doc.createElement("Key"); keyPackageElement.appendChild(keyElement); keyElement.setAttribute("Id", seed.getKeyId()); if (seed.getType().equals("TOTP")) { keyElement.setAttribute("Algorithm", "urn:ietf:params:xml:ns:keyprov:pskc:totp"); } else if (seed.getType().equals("HOTP")) { keyElement.setAttribute("Algorithm", "urn:ietf:params:xml:ns:keyprov:pskc:hotp"); } else { throw new Exception("OTP type not supported"); } /** * Issuer */ Element issuerElement = doc.createElement("Issuer"); issuerElement.setTextContent(seed.getIssuer()); keyElement.appendChild(issuerElement); /** * AlgorithmParameters */ Element algorithmParametersElement = doc.createElement("AlgorithmParameters"); keyElement.appendChild(algorithmParametersElement); /** * ResponseFormat */ Element responseFormatElement = doc.createElement("ResponseFormat"); algorithmParametersElement.appendChild(responseFormatElement); responseFormatElement.setAttribute("Length", seed.getLength()); responseFormatElement.setAttribute("Encoding", seed.getEncoding()); /** * Data */ Element dataElement = doc.createElement("Data"); keyElement.appendChild(dataElement); /** * Secret */ Element secretElement = doc.createElement("Secret"); dataElement.appendChild(secretElement); /** * EncryptedValue */ Element encryptedValueElement = doc.createElement("EncryptedValue"); secretElement.appendChild(encryptedValueElement); /** * xenc:EncryptionMethod */ Element encryptionMethodElement = doc.createElement("xenc:EncryptionMethod"); encryptedValueElement.appendChild(encryptionMethodElement); encryptionMethodElement.setAttribute("Algorithm", "http://www.w3.org/2001/04/xmlenc#aes128-cbc"); /** * xenc:CipherData */ Element cipherDataElement = doc.createElement("xenc:CipherData"); encryptedValueElement.appendChild(cipherDataElement); /** * xenc:CipherValue */ Element cipherValueElement = doc.createElement("xenc:CipherValue"); cipherValueElement.setTextContent(seed.getCipherValue()); cipherDataElement.appendChild(cipherValueElement); /** * ValueMAC */ Element valueMACElement = doc.createElement("ValueMAC"); valueMACElement.setTextContent(seed.getValueMac()); secretElement.appendChild(valueMACElement); /** * Counter */ Element counterElement = doc.createElement("Counter"); dataElement.appendChild(counterElement); /** * PlainValue */ Element counterPlainValueElement = doc.createElement("PlainValue"); counterPlainValueElement.setTextContent(seed.getCounter()); counterElement.appendChild(counterPlainValueElement); /** * TimeInterval */ Element timeIntervalElement = doc.createElement("TimeInterval"); dataElement.appendChild(timeIntervalElement); /** * PlainValue */ Element timeIntervalPlainValueElement = doc.createElement("PlainValue"); timeIntervalPlainValueElement.setTextContent(seed.getTimeInterval()); timeIntervalElement.appendChild(timeIntervalPlainValueElement); /** * Time */ Element timeElement = doc.createElement("Time"); dataElement.appendChild(timeElement); /** * PlainValue */ Element timePlainValueElement = doc.createElement("PlainValue"); timePlainValueElement.setTextContent(seed.getTime()); timeElement.appendChild(timePlainValueElement); } doc.normalizeDocument(); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new File(fileOut)); transformer.transform(source, result); } public String initializeCrypto(byte[] fragment1, byte[] fragment2, byte[] publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, Base64DecodingException, UnsupportedEncodingException, DestroyFailedException, DecoderException { return crypto.initAll(fragment1, fragment2, publicKey); } public String initializeCrypto(byte[] fragment1, byte[] fragment2) throws NoSuchAlgorithmException, InvalidKeySpecException, Base64DecodingException, NoSuchPaddingException, InvalidKeyException, DecoderException { crypto.initRsaOperations(fragment1, fragment2); crypto.initHmacOperations(); return crypto.initAesOperations(); } }