package won.protocol.message.processor.impl; import org.apache.jena.query.Dataset; import org.apache.jena.rdf.model.Model; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StopWatch; import won.cryptography.keymanagement.KeyPairAliasDerivationStrategy; import won.cryptography.rdfsign.WonKeysReaderWriter; import won.cryptography.service.CryptographyService; import won.protocol.message.WonMessage; import won.protocol.message.WonMessageEncoder; import won.protocol.message.WonMessageType; import won.protocol.message.processor.WonMessageProcessor; import won.protocol.message.processor.exception.WonMessageProcessingException; import java.security.PublicKey; /** * This processor is intended for use in owners (bot or webapp). * * If the message type is CREATE, the processor adds the appropriate public key to the need's RDF content. * * If the <code>fixedPrivateKeyAlias</code> property is set, the processor generates at most one key pair with that alias * and uses that key pair for all need it processes. * * If the <code>fixedPrivateKeyAlias</code> property is not set, the processor generates one keypair per need, using * the need URI as the keypair's alias. * * This processor should be removed when user's/need's key management and signing happens in * the Owner Client (browser). * * User: ypanchenko * Date: 10.04.2015 */ public class KeyForNewNeedAddingProcessor implements WonMessageProcessor { private static final Logger logger = LoggerFactory.getLogger(KeyForNewNeedAddingProcessor.class); private CryptographyService cryptographyService; ThreadLocal<StopWatch> stopWatchThreadLocal = new ThreadLocal<>(); private KeyPairAliasDerivationStrategy keyPairAliasDerivationStrategy; public KeyForNewNeedAddingProcessor() { } public void setCryptographyService(final CryptographyService cryptoService) { this.cryptographyService = cryptoService; } @Override public WonMessage process(final WonMessage message) throws WonMessageProcessingException { StopWatch stopWatch = getStopWatch(); try { if (message.getMessageType() == WonMessageType.CREATE_NEED) { String needUri = message.getSenderNeedURI().toString(); Dataset msgDataset = WonMessageEncoder.encodeAsDataset(message); // generate and add need's public key to the need content if (logger.isDebugEnabled()){ stopWatch.start(); } String alias = keyPairAliasDerivationStrategy.getAliasForNeedUri(needUri); if (cryptographyService.getPrivateKey(alias) == null) { cryptographyService.createNewKeyPair(alias, alias); } if (logger.isDebugEnabled()) { stopWatchStopAndLog(stopWatch); } PublicKey pubKey = cryptographyService.getPublicKey(alias); WonKeysReaderWriter keyWriter = new WonKeysReaderWriter(); String contentName = message.getContentGraphURIs().get(0); Model contentModel = msgDataset.getNamedModel(contentName); keyWriter.writeToModel(contentModel, contentModel.createResource(needUri), pubKey); return new WonMessage(msgDataset); } } catch (Exception e) { logger.error("Failed to add key", e); throw new WonMessageProcessingException("Failed to add key for need in message " + message.getMessageURI().toString()); } return message; } public void setKeyPairAliasDerivationStrategy(KeyPairAliasDerivationStrategy keyPairAliasDerivationStrategy) { this.keyPairAliasDerivationStrategy = keyPairAliasDerivationStrategy; } private void stopWatchStopAndLog(StopWatch stopWatch) { stopWatch.stop(); if (stopWatch.getTaskCount() % 10 == 0) { logger .debug("creating keypair takes {} millis on average", String.format("%.2f", ((double) stopWatch .getTotalTimeMillis() / stopWatch .getTaskCount()))); } } private StopWatch getStopWatch() { StopWatch stopWatch = stopWatchThreadLocal.get(); if (stopWatch == null) { stopWatch = new StopWatch(); stopWatchThreadLocal.set(stopWatch); } return stopWatch; } }