/* * [Sign.java] * * Summary: Digitally sign a message. * * Copyright: (c) 2004-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.4 2006-03-05 reformat with IntelliJ and add Javadoc. */ package com.mindprod.transporter; import java.io.IOException; import java.io.Serializable; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Digitally sign a message. *

* Uses compression, and base64u armouring. * No encryption. See Transporter.java for example of use. * * @author Roedy Green, Canadian Mind Products * @version 1.4 2006-03-05 reformat with IntelliJ and add Javadoc. * @since 2004-06-08 */ public final class Sign extends Wrap { /** * true if debugging */ private static final boolean DEBUGGING = false; /** * sender's private key. used to sign messages. */ private final PrivateKey senderPrivateKey; /** * constructor. * * @param senderPrivateKey sender's private key */ public Sign( PrivateKey senderPrivateKey ) { super(); this.senderPrivateKey = senderPrivateKey; } /** * prepend a digital signature to the message. * * @param unsignedMessage message to sign. * * @return signed message. * @throws IOException */ protected byte[] sign( byte[] unsignedMessage ) throws IOException { // format of a signed message: // ( 16-bits signature length) ( 32-bits encrypted salt, encrypted // digest ) ( unencrypted message all in one block ) // encrypted with sender's private key. try { if ( DEBUGGING ) { Tools.dumpBytes( "unsignedMessage", unsignedMessage ); } MessageDigest md = MessageDigest.getInstance( "MD5" ); md.update( unsignedMessage ); byte[] digest = md.digest(); if ( DEBUGGING ) { Tools.dumpBytes( "digest", digest ); } // like a one-block decrypt byte[] encryptedDigest = Tools.processWithPrivateKey( Tools.salt( digest ), senderPrivateKey ); if ( DEBUGGING ) { Tools.dumpBytes( "encryptedDigest", encryptedDigest ); } byte[] countedEncryptedDigest = Tools .prependLength( encryptedDigest ); byte[] signedMessage = new byte[ countedEncryptedDigest .length + unsignedMessage .length ]; Tools.insert( signedMessage, 0, countedEncryptedDigest, 0, countedEncryptedDigest.length ); Tools.insert( signedMessage, countedEncryptedDigest.length, unsignedMessage, 0, unsignedMessage.length ); if ( DEBUGGING ) { Tools.dumpBytes( "signedMessage", signedMessage ); } return signedMessage; } catch ( NoSuchAlgorithmException e ) { throw new IOException( "Java missing the MD5 class. Try version 1.4+ " + e.getMessage() ); } } /** * Wraps object for sending via CIA Post, serialised, compressed, encrypted and base64u armoured. Does not build * parm=value. * * @param o Object to wrap for sending. * * @return base64u-encoded string to send. * @throws IOException */ public String wrap( Serializable o ) throws IOException { return armour( sign( compress( serialize( o ) ) ) ); } } // end sign