package won.cryptography.rdfsign; import org.apache.jena.query.Dataset; import org.apache.jena.rdf.model.*; import org.apache.jena.vocabulary.RDF; import de.uni_koblenz.aggrimm.icp.crypto.sign.ontology.Ontology; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.interfaces.ECPublicKey; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECPublicKeySpec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import won.cryptography.exception.KeyNotSupportedException; import won.cryptography.key.KeyInformationExtractor; import won.cryptography.key.KeyInformationExtractorBouncyCastle; import won.protocol.util.RdfUtils; import won.protocol.vocabulary.CERT; import won.protocol.vocabulary.WONCRYPT; import javax.transaction.NotSupportedException; import java.math.BigInteger; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * A helper class to read from/write to RDF EC public key won representation, as well * read as key uri referenced in the signature. * * User: ypanchenko * Date: 27.03.2015 */ public class WonKeysReaderWriter { private static final Logger logger = LoggerFactory.getLogger(WonKeysReaderWriter.class); public WonKeysReaderWriter() { } public Map<String, PublicKey> readFromDataset(Dataset dataset) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { Map<String, PublicKey> keys = new HashMap<>(); readFromModel(dataset.getDefaultModel(), keys); for (String name : RdfUtils.getModelNames(dataset)) { readFromModel(dataset.getNamedModel(name), keys); } return keys; } public Set<PublicKey> readFromDataset(Dataset dataset, String keyUri) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { PublicKey key = readFromModel(dataset.getDefaultModel(), keyUri); Set<PublicKey> keys = new HashSet<>(); if (key != null) { keys.add(key); } for (String name : RdfUtils.getModelNames(dataset)) { key = readFromModel(dataset.getNamedModel(name), keyUri); if (key != null) { keys.add(key); } } return keys; } public Map<String, PublicKey> readFromModel(Model model) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { Map<String, PublicKey> keys = new HashMap<>(); readFromModel(model, keys); return keys; } public PublicKey readFromModel(Model model, String keyUri) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { Map<String, PublicKey> keys = new HashMap<>(); Resource keyRes = model.createResource(keyUri); readFromModel(model, keys, keyRes); return keys.get(keyUri); } private void readFromModel(final Model model, final Map<String, PublicKey> keys) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { readFromModel(model, keys, null); } private void readFromModel(final Model model, final Map<String, PublicKey> keys, Resource keyAgent) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { StmtIterator keyStmts = model.listStatements(keyAgent, CERT.KEY, RdfUtils.EMPTY_RDF_NODE); // TODO replace if with while if we allow multiple keys if (keyStmts.hasNext()) { Statement statement = keyStmts.next(); keyAgent = statement.getSubject(); RDFNode keyObj = statement.getObject(); // pub key statements NodeIterator ni = model.listObjectsOfProperty(keyObj.asResource(), CERT.PUBLIC_KEY); if (ni.hasNext()) { RDFNode eccKeyObj = ni.next(); // ECC pub key statements StmtIterator eccPubKeyStmts = model.listStatements(eccKeyObj.asResource(), RDF.type, WONCRYPT.ECC_PUBLIC_KEY); if (eccPubKeyStmts.hasNext()) { // extract properties of ECC public key: ni = model.listObjectsOfProperty(eccKeyObj.asResource(), WONCRYPT.ECC_ALGORITHM); String algName = null; String curveId = null; String qx = null; String qy = null; if (ni.hasNext()) { algName = ni.next().asLiteral().toString(); } else { return; } ni = model.listObjectsOfProperty(eccKeyObj.asResource(), WONCRYPT.ECC_CURVE_ID); if (ni.hasNext()) { curveId = ni.next().asLiteral().toString(); } else { return; } ni = model.listObjectsOfProperty(eccKeyObj.asResource(), WONCRYPT.ECC_QX); if (ni.hasNext()) { qx = ni.next().asLiteral().toString(); } else { return; } ni = model.listObjectsOfProperty(eccKeyObj.asResource(), WONCRYPT.ECC_QY); if (ni.hasNext()) { qy = ni.next().asLiteral().toString(); } else { return; } ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curveId); org.bouncycastle.math.ec.ECPoint ecPoint = ecSpec.getCurve() .createPoint(new BigInteger(qx, 16), new BigInteger(qy, 16)); ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(ecPoint, ecSpec); // TODO add provider to RDF triples? KeyFactory keyFactory = KeyFactory.getInstance(algName, "BC"); PublicKey key = keyFactory.generatePublic(pubKeySpec); keys.put(keyAgent.getURI(), key); } } } } public Set<String> readKeyReferences(Dataset dataset) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { Set<String> keyRefs = new HashSet<>(); for (String name : RdfUtils.getModelNames(dataset)) { readKeyReferences(dataset.getNamedModel(name), keyRefs); } return keyRefs; } public void readKeyReferences(Model model, Set<String> keyRefs) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { Property typeProp = model.createProperty(Ontology.getSigIri(), "hasVerificationCertificate"); StmtIterator si = model.listStatements(null, typeProp, RdfUtils.EMPTY_RDF_NODE); if (si.hasNext()) { keyRefs.add(si.next().getObject().asResource().getURI()); } } public void writeToModel(Model model, Resource keySubject, WonEccPublicKey pubKey) { // EC public key triples Resource bn = model.createResource(); Statement stmt = model.createStatement(bn, RDF.type, WONCRYPT.ECC_PUBLIC_KEY); model.add(stmt); stmt = model.createStatement(bn, WONCRYPT.ECC_ALGORITHM, pubKey.getAlgorithm()); model.add(stmt); stmt = model.createStatement(bn, WONCRYPT.ECC_CURVE_ID, pubKey.getCurveId()); model.add(stmt); stmt = model.createStatement(bn, WONCRYPT.ECC_QX, model.createLiteral(pubKey.getQx())); model.add(stmt); stmt = model.createStatement(bn, WONCRYPT.ECC_QY, model.createLiteral(pubKey.getQy())); model.add(stmt); // public key triple Resource bn2 = model.createResource(); stmt = model.createStatement(bn2, CERT.PUBLIC_KEY, bn); model.add(stmt); // key triple stmt = model.createStatement(keySubject, CERT.KEY, bn2); model.add(stmt); } public Model writeToModel(Resource keySubject, WonEccPublicKey pubKey) { Model model = ModelFactory.createDefaultModel(); writeToModel(model, keySubject, pubKey); return model; } public void writeToModel(Model model, Resource keySubject, PublicKey publicKey) throws NotSupportedException, KeyNotSupportedException { if (publicKey instanceof ECPublicKey) { KeyInformationExtractor info = new KeyInformationExtractorBouncyCastle(); writeToModel(model, keySubject, new WonEccPublicKey(info.getCurveID(publicKey), info.getAlgorithm(publicKey), info.getQX(publicKey), info.getQY(publicKey))); } else { throw new NotSupportedException("Not supported key: " + publicKey.getClass().getName()); } } }