package won.cryptography.message; import org.apache.jena.query.Dataset; import org.apache.jena.riot.Lang; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import won.cryptography.rdfsign.SignatureVerificationState; import won.cryptography.service.KeyStoreService; import won.cryptography.utils.TestSigningUtils; import won.protocol.message.WonMessage; import won.protocol.message.processor.impl.WonMessageSignerVerifier; import won.protocol.util.RdfUtils; import java.io.File; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.interfaces.ECPrivateKey; import java.util.HashMap; import java.util.Map; /** * User: ypanchenko * Date: 09.04.2015 */ public class WonMessageSignerVerifierTest { private static final String RESOURCE_FILE_SIG = "/won-signed-messages/create-need-msg.trig"; private static final String RESOURCE_OWNER_FILE_NOSIG = "/won-signed-messages/need-owner-msg-nosig.trig"; private static final String RESOURCE_NODE_FILE_NOSIG = "/won-signed-messages/need-node-msg-nosig.trig"; private static final String NEED_CORE_DATA_URI = "http://localhost:8080/won/resource/need/3144709509622353000/core/#data"; private static final String NEED_CORE_DATA_SIG_URI = "http://localhost:8080/won/resource/need/3144709509622353000/core/#data-sig"; private static final String EVENT_ENV1_URI = "http://localhost:8080/won/resource/event/7719577021233193000#data"; private static final String EVENT_ENV1_SIG_URI = "http://localhost:8080/won/resource/event/7719577021233193000#data-sig"; private static final String EVENT_ENV2_URI = "http://localhost:8080/won/resource/event/7719577021233193000#envelope-s7gl"; private static final String EVENT_ENV2_SIG_URI = "http://localhost:8080/won/resource/event/7719577021233193000#envelope-s7gl-sig"; Map<String,PublicKey> pubKeysMap = new HashMap<String,PublicKey>(); private PrivateKey needKey; private PrivateKey ownerKey; private PrivateKey nodeKey; @Before public void init() throws Exception { //load public keys: Security.addProvider(new BouncyCastleProvider()); File keysFile = new File(this.getClass().getResource(TestSigningUtils.KEYS_FILE).getFile()); KeyStoreService storeService = new KeyStoreService(keysFile, "temp"); storeService.setDefaultAlias(TestSigningUtils.ownerCertUri); storeService.init(); pubKeysMap.put(TestSigningUtils.needCertUri, storeService.getCertificate(TestSigningUtils.needCertUri).getPublicKey()); pubKeysMap.put(TestSigningUtils.ownerCertUri, storeService.getCertificate(TestSigningUtils.ownerCertUri).getPublicKey()); pubKeysMap.put(TestSigningUtils.nodeCertUri, storeService.getCertificate(TestSigningUtils.nodeCertUri).getPublicKey()); this.needKey = (ECPrivateKey) storeService.getPrivateKey(TestSigningUtils.needCertUri); // do we need owner key for some messages? e.g. when we send an error occurred // message not generated by owner client but by owner server? this.ownerKey = (ECPrivateKey) storeService.getPrivateKey(TestSigningUtils.ownerCertUri); this.nodeKey = (ECPrivateKey) storeService.getPrivateKey(TestSigningUtils.nodeCertUri); } @Test public void testVerify() throws Exception { // create signed dataset Dataset testDataset = TestSigningUtils.prepareTestDataset(RESOURCE_FILE_SIG); WonMessage testMsg = new WonMessage(testDataset); // verify SignatureVerificationState result = WonMessageSignerVerifier.verify(pubKeysMap, testMsg); Assert.assertTrue(result.getMessage(), result.isVerificationPassed()); Assert.assertEquals(3, result.getSignatureGraphNames().size()); Assert.assertEquals(NEED_CORE_DATA_URI, result.getSignedGraphName(NEED_CORE_DATA_SIG_URI)); Assert.assertEquals(EVENT_ENV1_URI, result.getSignedGraphName(EVENT_ENV1_SIG_URI)); Assert.assertEquals(EVENT_ENV2_URI, result.getSignedGraphName(EVENT_ENV2_SIG_URI)); } @Test public void signAndVerifyUnsignedMessage() throws Exception { // create signed dataset Dataset testDataset = TestSigningUtils.prepareTestDataset(RESOURCE_OWNER_FILE_NOSIG); WonMessage testMsg = new WonMessage(testDataset); // sign testMsg = WonMessageSignerVerifier.sign(needKey, pubKeysMap.get(TestSigningUtils.nodeCertUri), TestSigningUtils .needCertUri, testMsg); // pretend msg was serialized and deserialized in between //pretend it was serialized and deserialized String datasetString = RdfUtils.writeDatasetToString(testMsg.getCompleteDataset(), Lang.TRIG); testMsg = new WonMessage(RdfUtils.readDatasetFromString(datasetString, Lang.TRIG)); // verify SignatureVerificationState result = WonMessageSignerVerifier.verify(pubKeysMap, testMsg); Assert.assertTrue(result.isVerificationPassed()); Assert.assertEquals(2, result.getSignatureGraphNames().size()); Assert.assertEquals(NEED_CORE_DATA_URI, result.getSignedGraphName(NEED_CORE_DATA_SIG_URI)); Assert.assertEquals(EVENT_ENV1_URI, result.getSignedGraphName(EVENT_ENV1_SIG_URI)); // write for debugging TestSigningUtils.writeToTempFile(testMsg.getCompleteDataset()); } @Test public void signAndVerifySignedMessageNode() throws Exception { // create signed dataset Dataset testDataset = TestSigningUtils.prepareTestDataset(RESOURCE_NODE_FILE_NOSIG); WonMessage testMsg = new WonMessage(testDataset); // sign testMsg = WonMessageSignerVerifier.sign(nodeKey, pubKeysMap.get(TestSigningUtils.nodeCertUri), TestSigningUtils .nodeCertUri, testMsg); // pretend msg was serialized and deserialized in between //pretend it was serialized and deserialized String datasetString = RdfUtils.writeDatasetToString(testMsg.getCompleteDataset(), Lang.TRIG); testMsg = new WonMessage(RdfUtils.readDatasetFromString(datasetString, Lang.TRIG)); // verify SignatureVerificationState result = WonMessageSignerVerifier.verify(pubKeysMap, testMsg); Assert.assertTrue(result.getMessage(), result.isVerificationPassed()); Assert.assertEquals(3, result.getSignatureGraphNames().size()); Assert.assertEquals(NEED_CORE_DATA_URI, result.getSignedGraphName(NEED_CORE_DATA_SIG_URI)); Assert.assertEquals(EVENT_ENV1_URI, result.getSignedGraphName(EVENT_ENV1_SIG_URI)); Assert.assertEquals(EVENT_ENV2_URI, result.getSignedGraphName(EVENT_ENV2_SIG_URI)); // write for debugging TestSigningUtils.writeToTempFile(testMsg.getCompleteDataset()); } // TODO test more versions of not valid signatures, e.g. signatures missing, graphs missing, // wrong signature value, references signature values are wrong, etc. }