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.service.DefaultSecurityWonTransmissionService;
import won.cryptography.service.KeyStoreService;
import won.cryptography.utils.TestSigningUtils;
import won.cryptography.utils.TestingDataSource;
import won.protocol.message.WonMessage;
import won.protocol.message.WonMessageBuilder;
import won.protocol.message.WonMessageDirection;
import won.protocol.message.processor.exception.WonMessageProcessingException;
import won.protocol.message.processor.impl.SignatureAddingWonMessageProcessor;
import won.protocol.message.processor.impl.SignatureCheckingWonMessageProcessor;
import won.protocol.util.RdfUtils;
import java.io.File;
import java.net.URI;
import java.security.Security;
/**
* User: ypanchenko
* Date: 25.03.2015
*/
public class VerifyAndSignExamples
{
private static final String RESOURCE_FILE = "/won-signed-messages/create-need-msg.trig";
private static final String NEED_URI =
"http://localhost:8080/won/resource/need/3144709509622353000";
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 RESOURCE_FILE_NL = "/won-signed-messages/need-with-nl-nosig.trig";
SignatureAddingWonMessageProcessor nodeAddingProcessor;
SignatureAddingWonMessageProcessor ownerAddingProcessor;
SignatureCheckingWonMessageProcessor checkingProcessor;
@Before
public void init() throws Exception {
// initialize signature adding and signature checking processors:
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();
DefaultSecurityWonTransmissionService config = new DefaultSecurityWonTransmissionService();
config.setClientKeyStoreService(storeService);
config.initialize();
nodeAddingProcessor = new SignatureAddingWonMessageProcessor();
nodeAddingProcessor.setCryptographyService(config.getClientCryptographyService());
ownerAddingProcessor = new SignatureAddingWonMessageProcessor();
ownerAddingProcessor.setCryptographyService(config.getClientCryptographyService());
checkingProcessor = new SignatureCheckingWonMessageProcessor();
checkingProcessor.setLinkedDataSource(new TestingDataSource());
}
@Test
/**
* Owner Server receives create need message from Owner Client, adds public key (this
* step is omitted in the below example), and signs the message.
*/
public void ownerCreateNeedMsg() throws Exception {
// create dataset that contains need core data graph
Dataset inputDataset = TestSigningUtils.prepareTestDatasetFromNamedGraphs(RESOURCE_FILE,
new String[]{NEED_CORE_DATA_URI});
// owner adds need's public key - in this demo this step is omitted and we assume
// the key is already added - to avoid new key generation each time the demo is run.
// KeyForNewNeedAddingProcessor processor = new KeyForNewNeedAddingProcessor();
// WonMessage inputMessage = needKeyGeneratorAndAdder.process(inputMessage);
// owner adds envelope
WonMessage wonMessage = new WonMessageBuilder(URI.create(EVENT_ENV1_URI))
.setSenderNeedURI(URI.create(NEED_URI))
.addContent(inputDataset.getNamedModel(NEED_CORE_DATA_URI), null)
.setWonMessageDirection(WonMessageDirection.FROM_OWNER)
.build();
Dataset outputDataset = wonMessage.getCompleteDataset();
Assert.assertEquals(2, RdfUtils.getModelNames(outputDataset).size());
// write for debugging
TestSigningUtils.writeToTempFile(outputDataset);
// owner signs, - on behalf of need
WonMessage signedMessage = ownerAddingProcessor.processOnBehalfOfNeed(wonMessage);
outputDataset = signedMessage.getCompleteDataset();
// write for debugging
//TestSigningUtils.writeToTempFile(outputDataset);
Assert.assertEquals(4, RdfUtils.getModelNames(outputDataset).size());
// pretend it was serialized and deserialized
String datasetString = RdfUtils.writeDatasetToString(outputDataset, Lang.JSONLD);
outputDataset = RdfUtils.readDatasetFromString(datasetString, Lang.JSONLD);
WonMessage outputMessage = new WonMessage(outputDataset);
// write for debugging
//TestSigningUtils.writeToTempFile(outputDataset);
// the receiver of this message should be able to verify it
try {
checkingProcessor.process(outputMessage);
// if we got to here without exceptions - we were able to verify the signature
} catch (WonMessageProcessingException e) {
Assert.fail("Signature verification failed");
}
}
@Test
/**
* Node receives create need message, verifies it, if verification succeeds -
* adds envelope that includes reference to verified signatures, and signs it.
*/
public void nodeCreateNeedMsg() throws Exception {
// create dataset that contains need core data graph, envelope and its signatures.
// this is what nodes receives when the need is created
Dataset inputDataset = TestSigningUtils.prepareTestDatasetFromNamedGraphs(RESOURCE_FILE,
new String[]{NEED_CORE_DATA_URI,
NEED_CORE_DATA_SIG_URI,
EVENT_ENV1_URI,
EVENT_ENV1_SIG_URI,});
WonMessage inputMessage = new WonMessage(inputDataset);
// node verifies the signature:
WonMessage verifiedMessage = null;
try {
verifiedMessage = checkingProcessor.process(inputMessage);
} catch (WonMessageProcessingException e) {
Assert.fail("Signature verification failed");
}
// node then process the message in some way, and adds its own envelope,
// the envelope should contain the reference to the verified signatures
WonMessage nodeWonMessage = WonMessageBuilder.wrap(verifiedMessage)
.setWonMessageDirection(WonMessageDirection.FROM_SYSTEM)
.build();
Dataset outputDataset = nodeWonMessage.getCompleteDataset();
Assert.assertEquals(5, RdfUtils.getModelNames(outputDataset).size());
// write for debugging
//TestSigningUtils.writeToTempFile(outputDataset);
// node should then sign its envelope
WonMessage signedMessage = nodeAddingProcessor.process(nodeWonMessage);
Assert.assertEquals(6, RdfUtils.getModelNames(outputDataset).size());
// write for debugging
//TestSigningUtils.writeToTempFile(outputDataset);
// everyone should be able to verify this message, inculding when it was read from RDF:
String datasetString = RdfUtils.writeDatasetToString(signedMessage.getCompleteDataset(), Lang.TRIG);
WonMessage outputMessage = new WonMessage(RdfUtils.readDatasetFromString(datasetString, Lang.TRIG));
try {
checkingProcessor.process(outputMessage);
} catch (WonMessageProcessingException e) {
Assert.fail("Signature verification failed");
}
}
}