Listing 4. Bouncy Castle RSA signature generation in CryptoEngine
public byte [] RSASign (byte [] toSign) throws Exception {
if (RSAprivKey == null)
throw new Exception("Generate RSA keys first!");
SHA1Digest dig = new SHA1Digest();
RSAEngine eng = new RSAEngine();
PSSSigner signer = new PSSSigner(eng, dig, 64);
signer.init(true, RSAprivKey);
signer.update(toSign, 0, toSign.length);
return signer.generateSignature();
}
The receiving party must have prior knowledge of the public key and digest/signature algorithms to verify the signature:
Listing 5. Bouncy Castle RSA signature verification in CryptoEngine
public boolean RSAVerify (byte [] mesg, byte [] sig)
throws Exception {
if (RSApubKey == null)
throw new Exception("Generate RSA keys first!");
SHA1Digest dig = new SHA1Digest();
RSAEngine eng = new RSAEngine();
PSSSigner signer = new PSSSigner(eng, dig, 64);
signer.init(false, RSApubKey);
signer.update(mesg, 0, mesg.length);
return signer.verifySignature(sig);
}
Phaos Micro Foundation
Phaos MF supports DSA and RSA digital signatures. Generating DSA key pairs using the Phaos API is simple. Please note that variable DSApubKeyDer is not the public key itself. Rather, it is a byte array representation of the public key in DER (Distinguished Encoding Rules) format. The public key can be reconstructed from this array using an appropriate algorithm identifier. See more below:
Listing 6. Phaos DSA key pair generation in CryptoEngine
// 1024-bit DSA key
private DSAPrivateKey DSAprivKey;
// This is the DSA public key data you can serialize
private byte [] DSApubKeyDer;
public void generateDSAKeyPair () throws Exception {
DSAKeyGenParams params =
new DSAKeyGenParams(1024, RandomBitsSource.getDefault());
KeyPairGenerator kpg =
KeyPairGenerator.getInstance(OIDList.DSA, params);
KeyPair kp = kpg.generateKeyPair();
DSAprivKey = (DSAPrivateKey)kp.privateKey;
ByteArrayOutputStream baos = new ByteArrayOutputStream ();
((DSAPublicKey)kp.publicKey).output(baos);
DSApubKeyDer = baos.toByteArray();
return;
}
The Phaos API provides convenient ways for serializing keys. Note that in addition to keys themselves, you must serialize DSA key generation parameters for algorithm identification purposes:
Listing 7. Phaos DSA key pair serialization in keygensrc/GenerateAllKeys.java
DSAPublicKey pubKey = (DSAPublicKey)kp.publicKey;
DSAPrivateKey privKey = (DSAPrivateKey)kp.privateKey;
pubKey.output(new FileOutputStream(outdir + "DSApubKey.der"));
privKey.output(new FileOutputStream(outdir + "DSAprivKey.der"));
DSAParams dsaParams =
new DSAParams(
new ByteArrayInputStream(
privKey.createAlgID(true).encodeParameters()));
dsaParams.output(new FileOutputStream(outdir + "DSAparams.der"));
In CryptoEngine's constructor, we reconstruct the private key using private key DER data and the algorithm identifier. The public key DER data is also read in, but the public key itself is not reconstructed until the verification process starts:
Listing 8. Reconstruct Phaos DSA private key and read in public key data in CryptoEngine constructor
// The DSA private key
is = c.getResourceAsStream("/keys/DSAparams.der");
DSAParams params = new DSAParams(is);
AlgorithmIdentifier algID = getDSAalgID(params);
is.close();
is = c.getResourceAsStream("/keys/DSAprivKey.der");
DSAprivKey = new DSAPrivateKey(algID, is);
is.close();
// The DSA public key byte array
is = c.getResourceAsStream("/keys/DSApubKey.der");
baos = new ByteArrayOutputStream();
b = new byte[1];
while ( is.read(b) != -1 ) {
baos.write(b);
}
is.close();
DSApubKeyDer = baos.toByteArray();
baos.close();
The getDSAalgID() method used in the above listing also retrieves the algorithm identifier from DSA parameters:
Listing 9. Retrieve the algorithm identifier in CryptoEngine
private AlgorithmIdentifier getDSAalgID (DSAParams params)
throws Exception {
ByteArrayOutputStream paramsOut = new ByteArrayOutputStream();
params.output(paramsOut);
paramsOut.close();
return new AlgorithmIdentifier(OIDList.DSA,
paramsOut.toByteArray());
}
Now, we can sign a DSA signature using the private key. Note that both the Phaos algorithm identifier and the signature data itself are written into the output array:
Listing 10. Generate a Phaos DSA signature in CryptoEngine
public byte [] DSASign (byte [] toSign) throws Exception {
if (DSAprivKey == null)
throw new Exception("Generate DSA keys first!");
Signature signature =
Signature.getInstance(AlgIDList.SHA1_WITH_DSA,
DSAprivKey);
byte [] result =
signature.sign(toSign, 0, toSign.length).toByteArray(true);
DSAParams params = new DSAParams(
new ByteArrayInputStream(
DSAprivKey.createAlgID(true).encodeParameters()));
AlgorithmIdentifier algID = getDSAalgID (params);
ByteArrayOutputStream baos = new ByteArrayOutputStream ();
algID.output(baos);
baos.write(result, 0, result.length);
baos.flush();
baos.close();
return baos.toByteArray();
}