Update of /cvsroot/neuclear/neuclear-id/src/java/org/neuclear/signers
In directory sc8-pr-cvs1:/tmp/cvs-serv29589/src/java/org/neuclear/signers
Added Files:
DefaultSigner.java InvalidPassphraseException.java
JCESigner.java NonExistingSignerException.java
PublicKeySource.java SimpleSigner.java
Log Message:
Refactored the whole signing process. Now we have an interface called Signer which is the old SignerStore.
To use it you pass a byte array and an alias. The sign method then returns the signature.
If a Signer needs a passphrase it uses a PassPhraseAgent to present a dialogue box, read it from a command line etc.
This new Signer pattern allows us to use secure signing hardware such as N-Cipher in the future for server applications as well
as SmartCards for end user applications.
--- NEW FILE: DefaultSigner.java ---
package org.neuclear.signers;
import org.neuclear.commons.NeuClearException;
import org.neuclear.passphraseagents.PassPhraseAgent;
import org.neudist.crypto.CryptoTools;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
/*
NeuClear Distributed Transaction Clearing Platform
(C) 2003 Pelle Braendgaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id: DefaultSigner.java,v 1.1 2003/10/29 21:16:28 pelle Exp $
$Log: DefaultSigner.java,v $
Revision 1.1 2003/10/29 21:16:28 pelle
Refactored the whole signing process. Now we have an interface called Signer which is the old SignerStore.
To use it you pass a byte array and an alias. The sign method then returns the signature.
If a Signer needs a passphrase it uses a PassPhraseAgent to present a dialogue box, read it from a command line etc.
This new Signer pattern allows us to use secure signing hardware such as N-Cipher in the future for server applications as well
as SmartCards for end user applications.
*/
/**
* Easy to use preconfigured Signer that uses the standard default JCE KeyStore
* User: pelleb
* Date: Oct 29, 2003
* Time: 3:22:17 PM
*/
public class DefaultSigner extends JCESigner {
public DefaultSigner(PassPhraseAgent agent) throws NeuClearException, GeneralSecurityException {
super(CryptoTools.DEFAULT_KEYSTORE, KeyStore.getDefaultType(), null, agent);
}
}
--- NEW FILE: InvalidPassphraseException.java ---
/*
* $Id: InvalidPassphraseException.java,v 1.1 2003/10/29 21:16:28 pelle Exp $
* $Log: InvalidPassphraseException.java,v $
* Revision 1.1 2003/10/29 21:16:28 pelle
* Refactored the whole signing process. Now we have an interface called Signer which is the old SignerStore.
* To use it you pass a byte array and an alias. The sign method then returns the signature.
* If a Signer needs a passphrase it uses a PassPhraseAgent to present a dialogue box, read it from a command line etc.
* This new Signer pattern allows us to use secure signing hardware such as N-Cipher in the future for server applications as well
* as SmartCards for end user applications.
*
* Revision 1.2 2003/02/20 13:26:41 pelle
* Adding all of the modification from Rams?s Morales ra...@co... to support DSASHA1 Signatures
* Thanks Rams?s good work.
* So this means there is now support for:
* - DSA KeyInfo blocks
* - DSA Key Generation within CryptoTools
* - Signing using DSASHA1
*
* Revision 1.1 2003/02/18 00:03:32 pelle
* Moved the Signer classes from neudistframework into neudist-xmlsig
*
* Revision 1.2 2002/09/21 23:11:16 pelle
* A bunch of clean ups. Got rid of as many hard coded URL's as I could.
*
* User: pelleb
* Date: Sep 20, 2002
* Time: 12:39:46 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package org.neuclear.signers;
import org.neudist.crypto.CryptoException;
public class InvalidPassphraseException extends CryptoException {
public InvalidPassphraseException() {
super("Passphrase incorrect.");
}
public InvalidPassphraseException(String msg) {
super(msg);
}
}
--- NEW FILE: JCESigner.java ---
/*
* $Id: JCESigner.java,v 1.1 2003/10/29 21:16:28 pelle Exp $
* $Log: JCESigner.java,v $
* Revision 1.1 2003/10/29 21:16:28 pelle
* Refactored the whole signing process. Now we have an interface called Signer which is the old SignerStore.
* To use it you pass a byte array and an alias. The sign method then returns the signature.
* If a Signer needs a passphrase it uses a PassPhraseAgent to present a dialogue box, read it from a command line etc.
* This new Signer pattern allows us to use secure signing hardware such as N-Cipher in the future for server applications as well
* as SmartCards for end user applications.
*
* Revision 1.4 2003/10/28 23:44:03 pelle
* The GuiDialogAgent now works. It simply presents itself as a simple modal dialog box asking for a passphrase.
* The two Signer implementations both use it for the passphrase.
*
* Revision 1.3 2003/10/21 22:29:59 pelle
* Renamed NeudistException to NeuClearException and moved it to org.neuclear.commons where it makes more sense.
* Unhooked the XMLException in the xmlsig library from NeuClearException to make all of its exceptions an independent hierarchy.
* Obviously had to perform many changes throughout the code to support these changes.
*
* Revision 1.2 2003/02/20 13:26:41 pelle
* Adding all of the modification from Rams?s Morales ra...@co... to support DSASHA1 Signatures
* Thanks Rams?s good work.
* So this means there is now support for:
* - DSA KeyInfo blocks
* - DSA Key Generation within CryptoTools
* - Signing using DSASHA1
*
* Revision 1.1 2003/02/18 00:03:32 pelle
* Moved the Signer classes from neudistframework into neudist-xmlsig
*
* Revision 1.2 2003/02/09 00:15:55 pelle
* Fixed things so they now compile with r_0.7 of XMLSig
*
* Revision 1.1 2002/10/06 00:39:26 pelle
* I have now expanded support for different types of Signers.
* There is now a JCESigner which uses a JCE KeyStore for signing.
* I have refactored the SigningServlet a bit, eliminating most of the demo code.
* This has been moved into DemoSigningServlet.
* I have expanded the CommandLineSigner, so it now also has an option for specifying a default signing service.
* The default web application now contains two signers.
* - The Demo one is still at /Signer
* - There is a new one at /personal/Signer this uses the testkeys.ks for
* signing anything under neu://test
* Note neu://test now has a default interactive signer running on localhost.
* So to play with this you must install the webapp on your own local machine.
*
* Revision 1.2 2002/09/23 15:09:11 pelle
* Got the SimpleSigner working properly.
* I couldn't get SealedObjects working with BouncyCastle's Symmetric keys.
* Don't know what I was doing, so I reimplemented it. Encrypting
* and decrypting it my self.
*
* Revision 1.1 2002/09/21 23:11:16 pelle
* A bunch of clean ups. Got rid of as many hard coded URL's as I could.
*
* User: pelleb
* Date: Sep 20, 2002
* Time: 12:37:32 PM
*/
package org.neuclear.signers;
import org.neuclear.commons.NeuClearException;
import org.neuclear.passphraseagents.PassPhraseAgent;
import org.neudist.crypto.CryptoException;
import org.neudist.crypto.CryptoTools;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
/**
* Wrapper around JCE KeyStore
*/
public class JCESigner implements org.neudist.crypto.Signer, PublicKeySource {
public JCESigner(String filename, String type, String provider, PassPhraseAgent agent) throws NeuClearException, GeneralSecurityException {
this.agent = agent;
try {
if (filename == null)
throw new NeuClearException("Filename not given for JCESigner");
File file = new File(filename);
if (provider == null)
ks = KeyStore.getInstance(type);
else
ks = KeyStore.getInstance(type, provider);
if (file.exists()) {
System.out.println("NEUDIST: Loading KeyStore");
FileInputStream in = new FileInputStream(file);
ks.load(in, agent.getPassPhrase("KeyStore Passphrase for: " + file.getAbsolutePath()));
} else
throw new NeuClearException("KeyStore: " + file.getPath() + " doesnt exist");
} catch (IOException e) {
throw new NeuClearException(e);
}
}
private PrivateKey getKey(String name, char passphrase[]) throws InvalidPassphraseException, NonExistingSignerException, IOException {
try {
PrivateKey key = (PrivateKey) ks.getKey(name, passphrase);
if (key == null)
throw new NonExistingSignerException("No keys for: " + name);
return key;
} catch (ClassCastException e) {
throw new NonExistingSignerException("Incorrect Key type found");
} catch (GeneralSecurityException e) {
throw new InvalidPassphraseException(e.getLocalizedMessage());
}
}
/**
* Returns the PrivateKey corresponding to the given name.
*
* @param name Unique Name of PrivateKey
* @param data Data to be signed
* @return The signature
* @throws InvalidPassphraseException if the passphrase doesn't match
*/
public byte[] sign(String name, byte data[]) throws CryptoException {
try {
return CryptoTools.sign(getKey(name, agent.getPassPhrase(name)), data);
} catch (IOException e) {
throw new CryptoException(e);
}
}
public boolean canSignFor(String name) throws CryptoException {
try {
return ks.containsAlias(name);
} catch (KeyStoreException e) {
throw new CryptoException(e);
}
}
public PublicKey getPublicKey(String name) throws CryptoException {
try {
return ks.getCertificate(name).getPublicKey();
} catch (KeyStoreException e) {
throw new CryptoException(e);
}
}
private final KeyStore ks;
private final PassPhraseAgent agent;
}
--- NEW FILE: NonExistingSignerException.java ---
/*
* $Id: NonExistingSignerException.java,v 1.1 2003/10/29 21:16:28 pelle Exp $
* $Log: NonExistingSignerException.java,v $
* Revision 1.1 2003/10/29 21:16:28 pelle
* Refactored the whole signing process. Now we have an interface called Signer which is the old SignerStore.
* To use it you pass a byte array and an alias. The sign method then returns the signature.
* If a Signer needs a passphrase it uses a PassPhraseAgent to present a dialogue box, read it from a command line etc.
* This new Signer pattern allows us to use secure signing hardware such as N-Cipher in the future for server applications as well
* as SmartCards for end user applications.
*
* Revision 1.2 2003/02/20 13:26:41 pelle
* Adding all of the modification from Rams?s Morales ra...@co... to support DSASHA1 Signatures
* Thanks Rams?s good work.
* So this means there is now support for:
* - DSA KeyInfo blocks
* - DSA Key Generation within CryptoTools
* - Signing using DSASHA1
*
* Revision 1.1 2003/02/18 00:03:32 pelle
* Moved the Signer classes from neudistframework into neudist-xmlsig
*
* Revision 1.2 2002/09/21 23:11:16 pelle
* A bunch of clean ups. Got rid of as many hard coded URL's as I could.
*
* User: pelleb
* Date: Sep 21, 2002
* Time: 2:48:29 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package org.neuclear.signers;
import org.neudist.crypto.CryptoException;
public class NonExistingSignerException extends CryptoException {
public NonExistingSignerException() {
super("Couldnt Sign. Non existent key.");
}
public NonExistingSignerException(String name) {
super("Couldnt sign for: " + name);
}
}
--- NEW FILE: PublicKeySource.java ---
package org.neuclear.signers;
import org.neudist.crypto.CryptoException;
import java.security.PublicKey;
/*
NeuClear Distributed Transaction Clearing Platform
(C) 2003 Pelle Braendgaard
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id: PublicKeySource.java,v 1.1 2003/10/29 21:16:28 pelle Exp $
$Log: PublicKeySource.java,v $
Revision 1.1 2003/10/29 21:16:28 pelle
Refactored the whole signing process. Now we have an interface called Signer which is the old SignerStore.
To use it you pass a byte array and an alias. The sign method then returns the signature.
If a Signer needs a passphrase it uses a PassPhraseAgent to present a dialogue box, read it from a command line etc.
This new Signer pattern allows us to use secure signing hardware such as N-Cipher in the future for server applications as well
as SmartCards for end user applications.
*/
/**
* User: pelleb
* Date: Oct 29, 2003
* Time: 2:15:58 PM
*/
public interface PublicKeySource {
PublicKey getPublicKey(String name) throws CryptoException;
}
--- NEW FILE: SimpleSigner.java ---
/*
* $Id: SimpleSigner.java,v 1.1 2003/10/29 21:16:28 pelle Exp $
* $Log: SimpleSigner.java,v $
* Revision 1.1 2003/10/29 21:16:28 pelle
* Refactored the whole signing process. Now we have an interface called Signer which is the old SignerStore.
* To use it you pass a byte array and an alias. The sign method then returns the signature.
* If a Signer needs a passphrase it uses a PassPhraseAgent to present a dialogue box, read it from a command line etc.
* This new Signer pattern allows us to use secure signing hardware such as N-Cipher in the future for server applications as well
* as SmartCards for end user applications.
*
* Revision 1.4 2003/10/28 23:44:03 pelle
* The GuiDialogAgent now works. It simply presents itself as a simple modal dialog box asking for a passphrase.
* The two Signer implementations both use it for the passphrase.
*
* Revision 1.3 2003/10/21 22:29:59 pelle
* Renamed NeudistException to NeuClearException and moved it to org.neuclear.commons where it makes more sense.
* Unhooked the XMLException in the xmlsig library from NeuClearException to make all of its exceptions an independent hierarchy.
* Obviously had to perform many changes throughout the code to support these changes.
*
* Revision 1.2 2003/02/20 13:26:41 pelle
* Adding all of the modification from Rams?s Morales ra...@co... to support DSASHA1 Signatures
* Thanks Rams?s good work.
* So this means there is now support for:
* - DSA KeyInfo blocks
* - DSA Key Generation within CryptoTools
* - Signing using DSASHA1
*
* Revision 1.1 2003/02/18 00:03:32 pelle
* Moved the Signer classes from neudistframework into neudist-xmlsig
*
* Revision 1.5 2003/02/10 22:30:13 pelle
* Got rid of even further dependencies. In Particular OSCore
*
* Revision 1.4 2003/02/09 00:15:55 pelle
* Fixed things so they now compile with r_0.7 of XMLSig
*
* Revision 1.3 2002/10/06 00:39:26 pelle
* I have now expanded support for different types of Signers.
* There is now a JCESigner which uses a JCE KeyStore for signing.
* I have refactored the SigningServlet a bit, eliminating most of the demo code.
* This has been moved into DemoSigningServlet.
* I have expanded the CommandLineSigner, so it now also has an option for specifying a default signing service.
* The default web application now contains two signers.
* - The Demo one is still at /Signer
* - There is a new one at /personal/Signer this uses the testkeys.ks for
* signing anything under neu://test
* Note neu://test now has a default interactive signer running on localhost.
* So to play with this you must install the webapp on your own local machine.
*
* Revision 1.2 2002/09/23 15:09:11 pelle
* Got the SimpleSigner working properly.
* I couldn't get SealedObjects working with BouncyCastle's Symmetric keys.
* Don't know what I was doing, so I reimplemented it. Encrypting
* and decrypting it my self.
*
* Revision 1.1 2002/09/21 23:11:16 pelle
* A bunch of clean ups. Got rid of as many hard coded URL's as I could.
*
* User: pelleb
* Date: Sep 20, 2002
* Time: 12:37:32 PM
*/
package org.neuclear.signers;
import org.neuclear.commons.NeuClearException;
import org.neuclear.passphraseagents.PassPhraseAgent;
import org.neudist.crypto.CryptoException;
import org.neudist.crypto.CryptoTools;
import org.neudist.crypto.Signer;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import java.io.*;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* Simple memory based implementation of Signer.
* Currently it doesnt even use the passphrase. However it does do a SHA1 digest on the name first.
*/
public class SimpleSigner implements Signer {
public SimpleSigner(String file, PassPhraseAgent agent) throws NeuClearException, GeneralSecurityException {
this.agent = agent;
try {
signerFile = new File(file);
if (signerFile.exists()) {
System.out.println("NEUDIST: Loading KeyStore");
FileInputStream in = new FileInputStream(signerFile);
ObjectInputStream s = new ObjectInputStream(in);
ks = (HashMap) s.readObject();
} else
ks = new HashMap();
kf = KeyFactory.getInstance("RSA", "BC");
} catch (IOException e) {
throw new NeuClearException(e);
} catch (ClassNotFoundException e) {
throw new NeuClearException(e);
}
}
private PrivateKey getKey(String name, char passphrase[]) throws CryptoException, NonExistingSignerException {
System.out.println("NEUDIST: UnSealing key " + name + " ...");
byte encrypted[] = (byte[]) ks.get(getDigestedName(name));
if (encrypted == null)
throw new NonExistingSignerException("Signer " + name + "doesnt exist in this Store");
ByteArrayInputStream bis = new ByteArrayInputStream(encrypted);
byte keyBytes[] = new byte[0];
try {
Cipher c = CryptoTools.makePBECipher(Cipher.DECRYPT_MODE, passphrase);
CipherInputStream cin = new CipherInputStream(bis, c);
DataInputStream din = new DataInputStream(cin);
//byte keyBytes[]=new byte[c.getOutputSize(encrypted.length)];
if (din.readInt() != 11870) //This is just a quick check to see if the passphrase worked
throw new InvalidPassphraseException("Passphrase Didnt Match");
int i = din.readInt();
// Sanity Check
if (i > 5000)
throw new InvalidPassphraseException("Returned key is too big");
keyBytes = new byte[i];
din.readFully(keyBytes, 0, keyBytes.length);
din.close();
KeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
return kf.generatePrivate(spec);
} catch (GeneralSecurityException e) {
throw new InvalidPassphraseException(e.getLocalizedMessage());
} catch (IOException e) {
throw new CryptoException(e);
}
}
/**
* Adds the given key to the store.
*
* @param name The name to store it as
* @param passphrase The passphrase to encrypt the key
* @param key The PrivateKey itself.
*/
public void addKey(String name, char passphrase[], PrivateKey key) throws GeneralSecurityException, IOException {
System.out.println("NEUDIST: Sealing key: " + name + " in format " + key.getFormat());
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DataOutputStream dOut = new DataOutputStream(bOut);
Cipher c = CryptoTools.makePBECipher(Cipher.ENCRYPT_MODE, passphrase);
CipherOutputStream cOut = new CipherOutputStream(dOut, c);
dOut = new DataOutputStream(cOut);
dOut.writeInt(11870);//This is just a quick check to see if the passphrase worked
byte keyBytes[] = key.getEncoded(); //I'm assuming this is PKCS8, If not tough dooda
dOut.writeInt(keyBytes.length);
dOut.write(keyBytes);
dOut.close();
byte encrypted[] = bOut.toByteArray();
ks.put(getDigestedName(name), encrypted);
}
public boolean canSignFor(String name) throws CryptoException {
return ks.containsKey(getDigestedName(name));
}
static final protected String getDigestedName(String name) {
return new String(CryptoTools.digest(name.getBytes()));
}
public void save() throws IOException {
if (signerFile.getParent() != null)
signerFile.getParentFile().mkdirs();
FileOutputStream f = new FileOutputStream(signerFile);
ObjectOutput s = new ObjectOutputStream(f);
s.writeObject(ks);
s.flush();
}
public byte[] sign(String name, byte data[]) throws CryptoException {
return CryptoTools.sign(getKey(name, agent.getPassPhrase(name)), data);
}
private KeyFactory kf;
private Map ks;
private final File signerFile;
private final PassPhraseAgent agent;
}
|