* DSAEngine: Add code for alternate implementation using Java libs;
disabled by default. Add test code to verify identical results and compare speed.
This commit is contained in:
@ -29,10 +29,18 @@ package net.i2p.crypto;
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.KeyFactory;;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.DSAPrivateKeySpec;
|
||||||
|
import java.security.spec.DSAPublicKeySpec;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
@ -44,26 +52,67 @@ import net.i2p.util.Log;
|
|||||||
import net.i2p.util.NativeBigInteger;
|
import net.i2p.util.NativeBigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sign and verify using DSA-SHA1.
|
||||||
|
* Also contains methods to sign and verify using a SHA-256 Hash, used by Syndie only.
|
||||||
|
*
|
||||||
|
* The primary implementation is code from TheCryto.
|
||||||
|
* As of 0.8.7, also included is an alternate implementation using java.security libraries, which
|
||||||
|
* is slightly slower. This implementation could in the future be easily modified
|
||||||
|
* to use a new signing algorithm from java.security when we change the signing algorithm.
|
||||||
|
*
|
||||||
* Params and rv's changed from Hash to SHA1Hash for version 0.8.1
|
* Params and rv's changed from Hash to SHA1Hash for version 0.8.1
|
||||||
* Hash variants of sign() and verifySignature() restored in 0.8.3, required by Syndie.
|
* Hash variants of sign() and verifySignature() restored in 0.8.3, required by Syndie.
|
||||||
*/
|
*/
|
||||||
public class DSAEngine {
|
public class DSAEngine {
|
||||||
private Log _log;
|
private final Log _log;
|
||||||
private I2PAppContext _context;
|
private final I2PAppContext _context;
|
||||||
|
|
||||||
|
//private static final boolean _isAndroid = System.getProperty("java.vendor").contains("Android");
|
||||||
|
private static final boolean _useJavaLibs = false; // = _isAndroid;
|
||||||
|
|
||||||
public DSAEngine(I2PAppContext context) {
|
public DSAEngine(I2PAppContext context) {
|
||||||
_log = context.logManager().getLog(DSAEngine.class);
|
_log = context.logManager().getLog(DSAEngine.class);
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DSAEngine getInstance() {
|
public static DSAEngine getInstance() {
|
||||||
return I2PAppContext.getGlobalContext().dsa();
|
return I2PAppContext.getGlobalContext().dsa();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify using DSA-SHA1.
|
||||||
|
* Uses TheCrypto code unless configured to use the java.security libraries.
|
||||||
|
*/
|
||||||
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
|
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
|
||||||
return verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
|
boolean rv;
|
||||||
|
if (_useJavaLibs) {
|
||||||
|
try {
|
||||||
|
rv = altVerifySigSHA1(signature, signedData, verifyingKey);
|
||||||
|
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Lib Verify Fail, sig =\n" + signature + "\npubkey =\n" + verifyingKey);
|
||||||
|
return rv;
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Lib Verify Fail, sig =\n" + signature + "\npubkey =\n" + verifyingKey, gse);
|
||||||
|
// now try TheCrypto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv = verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
|
||||||
|
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("TheCrypto Verify Fail, sig =\n" + signature + "\npubkey =\n" + verifyingKey);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify using DSA-SHA1
|
||||||
|
*/
|
||||||
public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
|
public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
|
||||||
return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
|
return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify using DSA-SHA1
|
||||||
|
*/
|
||||||
public boolean verifySignature(Signature signature, InputStream in, SigningPublicKey verifyingKey) {
|
public boolean verifySignature(Signature signature, InputStream in, SigningPublicKey verifyingKey) {
|
||||||
return verifySignature(signature, calculateHash(in), verifyingKey);
|
return verifySignature(signature, calculateHash(in), verifyingKey);
|
||||||
}
|
}
|
||||||
@ -92,6 +141,8 @@ public class DSAEngine {
|
|||||||
byte[] sigbytes = signature.getData();
|
byte[] sigbytes = signature.getData();
|
||||||
byte rbytes[] = new byte[20];
|
byte rbytes[] = new byte[20];
|
||||||
byte sbytes[] = new byte[20];
|
byte sbytes[] = new byte[20];
|
||||||
|
//System.arraycopy(sigbytes, 0, rbytes, 0, 20);
|
||||||
|
//System.arraycopy(sigbytes, 20, sbytes, 0, 20);
|
||||||
for (int x = 0; x < 40; x++) {
|
for (int x = 0; x < 40; x++) {
|
||||||
if (x < 20) {
|
if (x < 20) {
|
||||||
rbytes[x] = sigbytes[x];
|
rbytes[x] = sigbytes[x];
|
||||||
@ -99,6 +150,7 @@ public class DSAEngine {
|
|||||||
sbytes[x - 20] = sigbytes[x];
|
sbytes[x - 20] = sigbytes[x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger s = new NativeBigInteger(1, sbytes);
|
BigInteger s = new NativeBigInteger(1, sbytes);
|
||||||
BigInteger r = new NativeBigInteger(1, rbytes);
|
BigInteger r = new NativeBigInteger(1, rbytes);
|
||||||
BigInteger y = new NativeBigInteger(1, verifyingKey.getData());
|
BigInteger y = new NativeBigInteger(1, verifyingKey.getData());
|
||||||
@ -106,6 +158,7 @@ public class DSAEngine {
|
|||||||
try {
|
try {
|
||||||
w = s.modInverse(CryptoConstants.dsaq);
|
w = s.modInverse(CryptoConstants.dsaq);
|
||||||
} catch (ArithmeticException ae) {
|
} catch (ArithmeticException ae) {
|
||||||
|
_log.warn("modInverse() error", ae);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
byte data[] = hash.getData();
|
byte data[] = hash.getData();
|
||||||
@ -130,15 +183,36 @@ public class DSAEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign using DSA-SHA1.
|
||||||
|
* Uses TheCrypto code unless configured to use the java.security libraries.
|
||||||
|
*/
|
||||||
public Signature sign(byte data[], SigningPrivateKey signingKey) {
|
public Signature sign(byte data[], SigningPrivateKey signingKey) {
|
||||||
|
if (_useJavaLibs) {
|
||||||
|
try {
|
||||||
|
return altSignSHA1(data, signingKey);
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Lib Sign Fail, privkey = " + signingKey, gse);
|
||||||
|
// now try TheCrypto
|
||||||
|
}
|
||||||
|
}
|
||||||
return sign(data, 0, data.length, signingKey);
|
return sign(data, 0, data.length, signingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign using DSA-SHA1
|
||||||
|
*/
|
||||||
public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
|
public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
|
||||||
if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
|
if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
|
||||||
SHA1Hash h = calculateHash(data, offset, length);
|
SHA1Hash h = calculateHash(data, offset, length);
|
||||||
return sign(h, signingKey);
|
return sign(h, signingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign using DSA-SHA1.
|
||||||
|
* Reads the stream until EOF. Does not close the stream.
|
||||||
|
*/
|
||||||
public Signature sign(InputStream in, SigningPrivateKey signingKey) {
|
public Signature sign(InputStream in, SigningPrivateKey signingKey) {
|
||||||
if ((signingKey == null) || (in == null) ) return null;
|
if ((signingKey == null) || (in == null) ) return null;
|
||||||
SHA1Hash h = calculateHash(in);
|
SHA1Hash h = calculateHash(in);
|
||||||
@ -192,28 +266,34 @@ public class DSAEngine {
|
|||||||
_context.random().harvester().feedEntropy("DSA.sign", rbytes, 0, rbytes.length);
|
_context.random().harvester().feedEntropy("DSA.sign", rbytes, 0, rbytes.length);
|
||||||
|
|
||||||
if (rbytes.length == 20) {
|
if (rbytes.length == 20) {
|
||||||
|
//System.arraycopy(rbytes, 0, out, 0, 20);
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
out[i] = rbytes[i];
|
out[i] = rbytes[i];
|
||||||
}
|
}
|
||||||
} else if (rbytes.length == 21) {
|
} else if (rbytes.length == 21) {
|
||||||
|
//System.arraycopy(rbytes, 1, out, 0, 20);
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
out[i] = rbytes[i + 1];
|
out[i] = rbytes[i + 1];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short rbytes.length [" + rbytes.length + "]");
|
if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short rbytes.length [" + rbytes.length + "]");
|
||||||
|
//System.arraycopy(rbytes, 0, out, 20 - rbytes.length, rbytes.length);
|
||||||
for (int i = 0; i < rbytes.length; i++)
|
for (int i = 0; i < rbytes.length; i++)
|
||||||
out[i + 20 - rbytes.length] = rbytes[i];
|
out[i + 20 - rbytes.length] = rbytes[i];
|
||||||
}
|
}
|
||||||
if (sbytes.length == 20) {
|
if (sbytes.length == 20) {
|
||||||
|
//System.arraycopy(sbytes, 0, out, 20, 20);
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
out[i + 20] = sbytes[i];
|
out[i + 20] = sbytes[i];
|
||||||
}
|
}
|
||||||
} else if (sbytes.length == 21) {
|
} else if (sbytes.length == 21) {
|
||||||
|
//System.arraycopy(sbytes, 1, out, 20, 20);
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
out[i + 20] = sbytes[i + 1];
|
out[i + 20] = sbytes[i + 1];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short sbytes.length [" + sbytes.length + "]");
|
if (_log.shouldLog(Log.DEBUG)) _log.debug("Using short sbytes.length [" + sbytes.length + "]");
|
||||||
|
//System.arraycopy(sbytes, 0, out, 40 - sbytes.length, sbytes.length);
|
||||||
for (int i = 0; i < sbytes.length; i++)
|
for (int i = 0; i < sbytes.length; i++)
|
||||||
out[i + 20 + 20 - sbytes.length] = sbytes[i];
|
out[i + 20 + 20 - sbytes.length] = sbytes[i];
|
||||||
}
|
}
|
||||||
@ -227,7 +307,11 @@ public class DSAEngine {
|
|||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return hash SHA-1 hash, NOT a SHA-256 hash */
|
/**
|
||||||
|
* Reads the stream until EOF. Does not close the stream.
|
||||||
|
*
|
||||||
|
* @return hash SHA-1 hash, NOT a SHA-256 hash
|
||||||
|
*/
|
||||||
public SHA1Hash calculateHash(InputStream in) {
|
public SHA1Hash calculateHash(InputStream in) {
|
||||||
MessageDigest digest = SHA1.getInstance();
|
MessageDigest digest = SHA1.getInstance();
|
||||||
byte buf[] = new byte[64];
|
byte buf[] = new byte[64];
|
||||||
@ -252,18 +336,222 @@ public class DSAEngine {
|
|||||||
return new SHA1Hash(digested);
|
return new SHA1Hash(digested);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternate to verifySignature() using java.security libraries.
|
||||||
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
|
* @since 0.8.7
|
||||||
|
*/
|
||||||
|
private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException {
|
||||||
|
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
||||||
|
KeyFactory keyFact = KeyFactory.getInstance("DSA");
|
||||||
|
// y p q g
|
||||||
|
KeySpec spec = new DSAPublicKeySpec(new NativeBigInteger(1, verifyingKey.getData()),
|
||||||
|
CryptoConstants.dsap,
|
||||||
|
CryptoConstants.dsaq,
|
||||||
|
CryptoConstants.dsag);
|
||||||
|
PublicKey pubKey = keyFact.generatePublic(spec);
|
||||||
|
jsig.initVerify(pubKey);
|
||||||
|
jsig.update(data);
|
||||||
|
boolean rv = jsig.verify(sigBytesToASN1(signature.getData()));
|
||||||
|
//if (!rv) {
|
||||||
|
// System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData()));
|
||||||
|
// System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(sigBytesToASN1(signature.getData())));
|
||||||
|
//}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternate to sign() using java.security libraries.
|
||||||
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
|
* @since 0.8.7
|
||||||
|
*/
|
||||||
|
private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||||
|
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
||||||
|
KeyFactory keyFact = KeyFactory.getInstance("DSA");
|
||||||
|
// y p q g
|
||||||
|
KeySpec spec = new DSAPrivateKeySpec(new NativeBigInteger(1, privateKey.getData()),
|
||||||
|
CryptoConstants.dsap,
|
||||||
|
CryptoConstants.dsaq,
|
||||||
|
CryptoConstants.dsag);
|
||||||
|
PrivateKey privKey = keyFact.generatePrivate(spec);
|
||||||
|
jsig.initSign(privKey, _context.random());
|
||||||
|
jsig.update(data);
|
||||||
|
return new Signature(aSN1ToSigBytes(jsig.sign()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html
|
||||||
|
* Signature Format ASN.1 sequence of two INTEGER values: r and s, in that order:
|
||||||
|
* SEQUENCE ::= { r INTEGER, s INTEGER }
|
||||||
|
*
|
||||||
|
* http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
|
||||||
|
* 30 -- tag indicating SEQUENCE
|
||||||
|
* xx - length in octets
|
||||||
|
*
|
||||||
|
* 02 -- tag indicating INTEGER
|
||||||
|
* xx - length in octets
|
||||||
|
* xxxxxx - value
|
||||||
|
*
|
||||||
|
* Convert to BigInteger and back so we have the minimum length representation, as required.
|
||||||
|
* r and s are always non-negative.
|
||||||
|
*
|
||||||
|
* @since 0.8.7
|
||||||
|
*/
|
||||||
|
private static byte[] sigBytesToASN1(byte[] sig) {
|
||||||
|
//System.out.println("pre TO asn1\n" + net.i2p.util.HexDump.dump(sig));
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(48);
|
||||||
|
baos.write(0x30);
|
||||||
|
baos.write(0); // length to be filled in below
|
||||||
|
|
||||||
|
byte[] tmp = new byte[20];
|
||||||
|
baos.write(2);
|
||||||
|
System.arraycopy(sig, 0, tmp, 0, 20);
|
||||||
|
BigInteger r = new BigInteger(1, tmp);
|
||||||
|
byte[] b = r.toByteArray();
|
||||||
|
baos.write(b.length);
|
||||||
|
baos.write(b, 0, b.length);
|
||||||
|
|
||||||
|
baos.write(2);
|
||||||
|
System.arraycopy(sig, 20, tmp, 0, 20);
|
||||||
|
BigInteger s = new BigInteger(1, tmp);
|
||||||
|
b = s.toByteArray();
|
||||||
|
baos.write(b.length);
|
||||||
|
baos.write(b, 0, b.length);
|
||||||
|
byte[] rv = baos.toByteArray();
|
||||||
|
rv[1] = (byte) (rv.length - 2);
|
||||||
|
//System.out.println("post TO asn1\n" + net.i2p.util.HexDump.dump(rv));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See above.
|
||||||
|
* @since 0.8.7
|
||||||
|
*/
|
||||||
|
private static byte[] aSN1ToSigBytes(byte[] asn) {
|
||||||
|
//System.out.println("pre from asn1\n" + net.i2p.util.HexDump.dump(asn));
|
||||||
|
byte[] rv = new byte[40];
|
||||||
|
int rlen = asn[3];
|
||||||
|
if ((asn[4] & 0x80) != 0)
|
||||||
|
throw new IllegalArgumentException("R is negative");
|
||||||
|
if (rlen > 21)
|
||||||
|
throw new IllegalArgumentException("R too big " + rlen);
|
||||||
|
else if (rlen == 21) {
|
||||||
|
System.arraycopy(asn, 5, rv, 0, 20);
|
||||||
|
} else
|
||||||
|
System.arraycopy(asn, 4, rv, 20 - rlen, rlen);
|
||||||
|
int slenloc = 25 + rlen - 20;
|
||||||
|
int slen = asn[slenloc];
|
||||||
|
if ((asn[slenloc + 1] & 0x80) != 0)
|
||||||
|
throw new IllegalArgumentException("S is negative");
|
||||||
|
if (slen > 21)
|
||||||
|
throw new IllegalArgumentException("S too big " + slen);
|
||||||
|
else if (slen == 21) {
|
||||||
|
System.arraycopy(asn, slenloc + 2, rv, 20, 20);
|
||||||
|
} else
|
||||||
|
System.arraycopy(asn, slenloc + 1, rv, 40 - slen, slen);
|
||||||
|
//System.out.println("post from asn1\n" + net.i2p.util.HexDump.dump(rv));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int RUNS = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run consistency and speed tests with both TheCrypto and java.security libraries.
|
||||||
|
*
|
||||||
|
* TheCrypto is about 5-15% faster than java.security.
|
||||||
|
*/
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||||
byte data[] = new byte[4096];
|
byte data[] = new byte[1024];
|
||||||
|
// warmump
|
||||||
ctx.random().nextBytes(data);
|
ctx.random().nextBytes(data);
|
||||||
Object keys[] = ctx.keyGenerator().generateSigningKeypair();
|
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < 10; i++) {
|
Thread.sleep(1000);
|
||||||
Signature sig = ctx.dsa().sign(data, (SigningPrivateKey)keys[1]);
|
} catch (InterruptedException ie) {}
|
||||||
boolean ok = ctx.dsa().verifySignature(sig, data, (SigningPublicKey)keys[0]);
|
SimpleDataStructure keys[] = null;
|
||||||
System.out.println("OK: " + ok);
|
|
||||||
|
System.err.println("100 runs with new data and keys each time");
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
ctx.random().nextBytes(data);
|
||||||
|
keys = ctx.keyGenerator().generateSigningKeys();
|
||||||
|
Signature sig = ctx.dsa().sign(data, (SigningPrivateKey)keys[1]);
|
||||||
|
Signature jsig = null;
|
||||||
|
try {
|
||||||
|
jsig = ctx.dsa().altSignSHA1(data, (SigningPrivateKey)keys[1]);
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
gse.printStackTrace();
|
||||||
}
|
}
|
||||||
} catch (Exception e) { e.printStackTrace(); }
|
boolean ok = ctx.dsa().verifySignature(jsig, data, (SigningPublicKey)keys[0]);
|
||||||
ctx.random().saveSeed();
|
boolean usok = ctx.dsa().verifySignature(sig, data, (SigningPublicKey)keys[0]);
|
||||||
}
|
boolean jok = false;
|
||||||
|
try {
|
||||||
|
jok = ctx.dsa().altVerifySigSHA1(sig, data, (SigningPublicKey)keys[0]);
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
gse.printStackTrace();
|
||||||
|
}
|
||||||
|
boolean jjok = false;;
|
||||||
|
try {
|
||||||
|
jjok = ctx.dsa().altVerifySigSHA1(jsig, data, (SigningPublicKey)keys[0]);
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
gse.printStackTrace();
|
||||||
|
}
|
||||||
|
System.err.println("TC->TC OK: " + usok + " JL->TC OK: " + ok + " TC->JK OK: " + jok + " JL->JL OK: " + jjok);
|
||||||
|
if (!(ok && usok && jok && jjok)) {
|
||||||
|
System.out.println("privkey\n" + net.i2p.util.HexDump.dump(keys[1].getData()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.err.println("Starting speed test");
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < RUNS; i++) {
|
||||||
|
Signature sig = ctx.dsa().sign(data, (SigningPrivateKey)keys[1]);
|
||||||
|
boolean ok = ctx.dsa().verifySignature(sig, data, (SigningPublicKey)keys[0]);
|
||||||
|
if (!ok) {
|
||||||
|
System.err.println("TheCrypto FAIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long time = System.currentTimeMillis() - start;
|
||||||
|
System.err.println("Time for " + RUNS + " DSA sign/verifies:");
|
||||||
|
System.err.println("TheCrypto time (ms): " + time);
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < RUNS; i++) {
|
||||||
|
boolean ok = false;
|
||||||
|
try {
|
||||||
|
Signature jsig = ctx.dsa().altSignSHA1(data, (SigningPrivateKey)keys[1]);
|
||||||
|
ok = ctx.dsa().altVerifySigSHA1(jsig, data, (SigningPublicKey)keys[0]);
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
gse.printStackTrace();
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
System.err.println("JavaLib FAIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time = System.currentTimeMillis() - start;
|
||||||
|
System.err.println("JavaLib time (ms): " + time);
|
||||||
|
|
||||||
|
/**** yes, arraycopy is slower for 20 bytes
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
byte b[] = new byte[20];
|
||||||
|
for (int i = 0; i < 10000000; i++) {
|
||||||
|
data[0] = data[i % 256];
|
||||||
|
System.arraycopy(data, 0, b, 0, 20);
|
||||||
|
}
|
||||||
|
time = System.currentTimeMillis() - start;
|
||||||
|
System.err.println("arraycopy time (ms): " + time);
|
||||||
|
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < 10000000; i++) {
|
||||||
|
data[0] = data[i % 256];
|
||||||
|
for (int j = 0; j < 20; j++) {
|
||||||
|
b[j] = data[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time = System.currentTimeMillis() - start;
|
||||||
|
System.err.println("loop time (ms): " + time);
|
||||||
|
****/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user