Enterprise J2ME Developing Mobile Java Applications [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Enterprise J2ME Developing Mobile Java Applications [Electronic resources] - نسخه متنی

Michael Juntao Yuan

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید



20.5 Digital Signature


Digital signature can guarantee message integrity and authenticity in an open network environment. To generate a signature, you first calculate a hash (also called digest) of your message. Then you encrypt that hash with your private key to generate a signature. The party at the receiving end first decrypts your signature into a hash using your public key. Then she calculates the hash from your message. If the two hashes match, the message is indeed from you and unaltered. The signing and verification processes are demonstrated in Figures 20.5 and 20.6 respectively.


Figure 20.5. Generate a digital signature.



Figure 20.6. Verify a digital signature.


If someone altered the message during its transmission and generated a new hash based on the modified message, public key algorithms guarantee that he cannot produce a matching signature without knowing your private key. The two parties must share four pieces of information: the message itself, its digital signature, the hash and signing algorithms, and the public key. Our demo MIDlet for digital signature is shown in Figure 20.7.


Figure 20.7. NTRUSign signature generation and verification.


Resources" section.


20.5.1 Bouncy Castle


Bouncy Castle supports DSA, RSA, and ECC (Elliptic Curve Cryptography) digital signature algorithms. But only RSA seems to have an acceptable performance on MIDP devices. So, the code example here only shows how to work with RSA signatures. Since the RSA key pair generation and serialization part is already covered by the last section, we go directly to the code for signature generation and verification (Listing 20.34).

Listing 20.34. Sign and verify a message using the RSA algorithm in BC



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, O, toSign.length);
return signer.generateSignature();
}
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);
}


20.5.2 IAIK JCE-ME


Our IAIK digital signature example also uses the RSA algorithm. So, again, we do not show any code for the key generation and serialization. Listing 20.35 demonstrates the signing and verification processes.

Listing 20.35. RSA digital signature sign and verify methods in IAIK



// RSA signature
public byte [] RSASign (byte [] toSign) throws Exception {
if (RSAprivKey == null)
throw new Exception("Generate RSA keys first!");
Signature sharsa = Signature.getInstance("SHA1withRSA");
sharsa.initSign(RSAprivKey, null);
sharsa.update(toSign);
return sharsa.sign();
}
// RSA signature verification
public boolean RSAVerify (byte [] mesg, byte [] sig)
throws Exception {
if (RSApubKey == null)
throw new Exception("Generate RSA keys first!");
Signature sharsa = Signature.getInstance("SHA1withRSA");
sharsa.initVerify(RSApubKey);
sharsa.update(mesg);
return sharsa.verify(sig);
}


20.5.3 Phaos Micro Foundation


Phaos MF supports DSA and RSA digital signatures. DSA is certainly slower than RSA. But since we already have two RSA examples, we will have a look at a DSA example here. Generating DSA key pairs using the Phaos MF API is illustrated in Listing 20.36. 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 Listing 20.38).

Listing 20.36. Phaos MF DSA key pair generation



// 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 DSA key pair serialization and deserialization processes are illustrated in Listings 20.37 and 20.38.

Listing 20.37. Phaos MF DSA key pair serialization



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"));

Listing 20.38. Phaos MF DSA key pair deserialization


// 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 method getDSAalgID() (Listing 20.38) retrieves the algorithm identifier from DSA parameters. It is also used in DSA sign and verify examples (Listing 20.39).

Listing 20.39. Phaos MF DSA sign and verify methods



private AlgorithmIdentifier getDSAalgID (DSAParams params)
throws Exception {
ByteArrayOutputStream paramsOut = new ByteArrayOutputStream();
params.output(paramsOut);
paramsOut.close();
return new AlgorithmIdentifier(OIDList.DSA, paramsOut.toByteArray());
}
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();
}
public boolean DSAVerify (byte [] mesg, byte [] sig)
throws Exception {
InputStream is = new ByteArrayInputStream(sig);
AlgorithmIdentifier algID = new AlgorithmIdentifier(is);
PooledArray sigBytes = ByteArrayPool.getArray(is.available());
is.read(sigBytes.buffer, 0, sigBytes.length);
is.close();
DSAPublicKey DSApubKey = new DSAPublicKey(algID,
new ByteArrayInputStream(DSApubKeyDer));
Signature signature =
Signature.getInstance(AlgIDList.SHA1_WITH_DSA, DSApubKey);
return signature.verify(mesg, 0, mesg.length,
sigBytes.buffer, 0, sigBytes.length);
}


20.5.4 NTRU jNeo


The NTRU digital signature algorithm (NTRUSign) uses different keys from the NTRUEncrypt algorithm. The key generation process is simple (Listing 20.40).

Note

Unlike RSA and DSA, the public and private keys in the NTRU digital signature algorithm are not exchangeable. You can sign only with the private key and verify only with the public key.

Listing 20.40. Generate an NTRU signature key pair



public void generateNTRUsgnKeys () throws Exception {
NTRUsgnKeys = new SgnKeys(ctx,
NTRUConst.NTRU_KEYSTRENGTH_251,
NTRUConst.NTRU_SHA1_HASH);
return;
}

The serialization and deserialization of the key pair are illustrated in Listing 20.41 and 20.42.

Listing 20.41. Serialize the NTRUSign key pair



byte [] pubKey = NTRUsgnKeys.exportPrivKey(null, 0);
out = new FileOutputStream(outdir + "SgnPubKey.dat");
out.write(pubKey);
out.flush(); out.close();
byte [] privKey = NTRUsgnKeys.exportPrivKey(null, 0);
out = new FileOutputStream(outdir + "SgnPrivKey.dat");
out.write(privKey);
out.flush(); out.close();

Listing 20.42. Deserialize the NTRUSign key pair


is = c.getResourceAsStream("/keys/SgnPubKey.dat");
byte [] sgnPubKeyData = readFromStream(is);
is.close();
is = c.getResourceAsStream("/keys/SgnPrivKey.dat");
byte [] sgnPrivKeyData = readFromStream(is);
is.close();
NTRUsgnKeys = new SgnKeys (sgnPubKeyData, 0,
sgnPubKeyData.length,
sgnPrivKeyData, 0,
sgnPrivKeyData.length);

The NTRU signature generation and verification processes are illustrated in Listing 20.43.

Listing 20.43. NTRUSign signature signing and verification using jNeo



public byte [] NTRUSign (byte [] message) throws Exception {
if ( NTRUsgnKeys == null )
throw new Exception("Generate keys first!");
MessageDigest dig = new MessageDigest(NTRUConst.NTRU_SHA160_HASH);
Signature sig =
new Signature(NTRUConst.NTRU_KEYSTRENGTH_251,
NTRUConst.NTRU_SHA160_HASH);
dig.updateMessageDigest(message, 0, message.length);
dig.completeMessageDigest();
sig.sign(ctx, NTRUsgnKeys, dig);
return sig.export();
}
public boolean NTRUVerify (byte [] message,
byte [] sigData) throws Exception {
Signature sig = new Signature(sigData, 0, sigData.length);
MessageDigest dig = new MessageDigest(sig.getHashAlg());
dig.updateMessageDigest(message, 0, message.length);
dig.completeMessageDigest();
try {
sig.verify(ctx, NTRUsgnKeys, dig);
return true;
} catch (NTRUException e) {
return false;
}
}


/ 204