forked from I2P_Developers/i2p.i2p
* Crypto: More implementation for key certs
- Support i2cp.destination.sigType option in TunnelController and I2PSocketManagerFactory - Fixup of Destination.create() and Destination.size() - Add generic off/len methods in DSAEngine, needed for streaming - Fixup of sign/verify in streaming Packet - Javadocs
This commit is contained in:
@ -41,6 +41,11 @@ public interface I2PClient {
|
||||
/** @since 0.8.1 */
|
||||
public final static String PROP_RELIABILITY_NONE = "none";
|
||||
|
||||
/** @since 0.9.11 */
|
||||
public static final String PROP_SIGTYPE = "i2cp.destination.sigType";
|
||||
/** @since 0.9.11 */
|
||||
public static final SigType DEFAULT_SIGTYPE = SigType.DSA_SHA1;
|
||||
|
||||
/**
|
||||
* For router->client payloads.
|
||||
*
|
||||
|
@ -47,7 +47,7 @@ class I2PClientImpl implements I2PClient {
|
||||
* format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
|
||||
*/
|
||||
public Destination createDestination(OutputStream destKeyStream) throws I2PException, IOException {
|
||||
return createDestination(destKeyStream, SigType.DSA_SHA1);
|
||||
return createDestination(destKeyStream, DEFAULT_SIGTYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,13 +89,20 @@ public class DSAEngine {
|
||||
* Uses TheCrypto code for DSA-SHA1 unless configured to use the java.security libraries.
|
||||
*/
|
||||
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
|
||||
return verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify using any sig type as of 0.9.11 (DSA only prior to that)
|
||||
*/
|
||||
public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
|
||||
boolean rv;
|
||||
SigType type = signature.getType();
|
||||
if (type != verifyingKey.getType())
|
||||
throw new IllegalArgumentException("type mismatch sig=" + signature.getType() + " key=" + verifyingKey.getType());
|
||||
if (type != SigType.DSA_SHA1) {
|
||||
try {
|
||||
rv = altVerifySig(signature, signedData, verifyingKey);
|
||||
rv = altVerifySig(signature, signedData, offset, size, verifyingKey);
|
||||
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||
_log.warn(type + " Sig Verify Fail");
|
||||
return rv;
|
||||
@ -107,7 +114,7 @@ public class DSAEngine {
|
||||
}
|
||||
if (_useJavaLibs) {
|
||||
try {
|
||||
rv = altVerifySigSHA1(signature, signedData, verifyingKey);
|
||||
rv = altVerifySigSHA1(signature, signedData, offset, size, verifyingKey);
|
||||
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||
_log.warn("Lib DSA Sig Verify Fail");
|
||||
return rv;
|
||||
@ -117,19 +124,12 @@ public class DSAEngine {
|
||||
// now try TheCrypto
|
||||
}
|
||||
}
|
||||
rv = verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
|
||||
rv = verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
|
||||
if ((!rv) && _log.shouldLog(Log.WARN))
|
||||
_log.warn("TheCrypto DSA Sig Verify Fail");
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify using DSA-SHA1 ONLY
|
||||
*/
|
||||
public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
|
||||
return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify using DSA-SHA1 ONLY
|
||||
*/
|
||||
@ -256,16 +256,26 @@ public class DSAEngine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign using DSA-SHA1 or ECDSA.
|
||||
* Sign using any key type.
|
||||
* Uses TheCrypto code unless configured to use the java.security libraries.
|
||||
*
|
||||
* @return null on error
|
||||
*/
|
||||
public Signature sign(byte data[], SigningPrivateKey signingKey) {
|
||||
return sign(data, 0, data.length, signingKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign using any key type as of 0.9.11 (DSA-SHA1 only prior to that)
|
||||
*
|
||||
* @return null on error
|
||||
*/
|
||||
public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
|
||||
if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
|
||||
SigType type = signingKey.getType();
|
||||
if (type != SigType.DSA_SHA1) {
|
||||
try {
|
||||
return altSign(data, signingKey);
|
||||
return altSign(data, offset, length, signingKey);
|
||||
} catch (GeneralSecurityException gse) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(type + " Sign Fail", gse);
|
||||
@ -274,23 +284,13 @@ public class DSAEngine {
|
||||
}
|
||||
if (_useJavaLibs) {
|
||||
try {
|
||||
return altSignSHA1(data, signingKey);
|
||||
return altSignSHA1(data, offset, length, 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign using DSA-SHA1 ONLY
|
||||
*
|
||||
* @return null on error
|
||||
*/
|
||||
public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
|
||||
if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
|
||||
SHA1Hash h = calculateHash(data, offset, length);
|
||||
return sign(h, signingKey);
|
||||
}
|
||||
@ -495,20 +495,20 @@ public class DSAEngine {
|
||||
/**
|
||||
* Generic verify DSA_SHA1, ECDSA, or RSA
|
||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||
* @since 0.9.9
|
||||
* @since 0.9.9 added off/len 0.9.11
|
||||
*/
|
||||
private boolean altVerifySig(Signature signature, byte[] data, SigningPublicKey verifyingKey)
|
||||
private boolean altVerifySig(Signature signature, byte[] data, int offset, int len, SigningPublicKey verifyingKey)
|
||||
throws GeneralSecurityException {
|
||||
SigType type = signature.getType();
|
||||
if (type != verifyingKey.getType())
|
||||
throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
|
||||
if (type == SigType.DSA_SHA1)
|
||||
return altVerifySigSHA1(signature, data, verifyingKey);
|
||||
return altVerifySigSHA1(signature, data, offset, len, verifyingKey);
|
||||
|
||||
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||
PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
|
||||
jsig.initVerify(pubKey);
|
||||
jsig.update(data);
|
||||
jsig.update(data, offset, len);
|
||||
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
||||
return rv;
|
||||
}
|
||||
@ -555,13 +555,14 @@ public class DSAEngine {
|
||||
/**
|
||||
* Alternate to verifySignature() using java.security libraries.
|
||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||
* @since 0.8.7
|
||||
* @since 0.8.7 added off/len 0.9.11
|
||||
*/
|
||||
private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException {
|
||||
private boolean altVerifySigSHA1(Signature signature, byte[] data, int offset,
|
||||
int len, SigningPublicKey verifyingKey) throws GeneralSecurityException {
|
||||
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
||||
PublicKey pubKey = SigUtil.toJavaDSAKey(verifyingKey);
|
||||
jsig.initVerify(pubKey);
|
||||
jsig.update(data);
|
||||
jsig.update(data, offset, len);
|
||||
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
||||
//if (!rv) {
|
||||
// System.out.println("BAD SIG\n" + net.i2p.util.HexDump.dump(signature.getData()));
|
||||
@ -573,17 +574,18 @@ public class DSAEngine {
|
||||
/**
|
||||
* Generic sign DSA_SHA1, ECDSA, or RSA
|
||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||
* @since 0.9.9
|
||||
* @since 0.9.9 added off/len 0.9.11
|
||||
*/
|
||||
private Signature altSign(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||
private Signature altSign(byte[] data, int offset, int len,
|
||||
SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||
SigType type = privateKey.getType();
|
||||
if (type == SigType.DSA_SHA1)
|
||||
return altSignSHA1(data, privateKey);
|
||||
return altSignSHA1(data, offset, len, privateKey);
|
||||
|
||||
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||
PrivateKey privKey = SigUtil.toJavaKey(privateKey);
|
||||
jsig.initSign(privKey, _context.random());
|
||||
jsig.update(data);
|
||||
jsig.update(data, offset, len);
|
||||
return SigUtil.fromJavaSig(jsig.sign(), type);
|
||||
}
|
||||
|
||||
@ -622,13 +624,14 @@ public class DSAEngine {
|
||||
/**
|
||||
* Alternate to sign() using java.security libraries.
|
||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||
* @since 0.8.7
|
||||
* @since 0.8.7 added off/len args 0.9.11
|
||||
*/
|
||||
private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||
private Signature altSignSHA1(byte[] data, int offset, int len,
|
||||
SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||
java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
|
||||
PrivateKey privKey = SigUtil.toJavaDSAKey(privateKey);
|
||||
jsig.initSign(privKey, _context.random());
|
||||
jsig.update(data);
|
||||
jsig.update(data, offset, len);
|
||||
return SigUtil.fromJavaSig(jsig.sign(), SigType.DSA_SHA1);
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,16 @@ public class Destination extends KeysAndCert {
|
||||
PublicKey pk = PublicKey.create(in);
|
||||
SigningPublicKey sk = SigningPublicKey.create(in);
|
||||
Certificate c = Certificate.create(in);
|
||||
byte[] padding;
|
||||
if (c.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
|
||||
// convert SPK to new SPK and padding
|
||||
KeyCertificate kcert = c.toKeyCertificate();
|
||||
padding = sk.getPadding(kcert);
|
||||
sk = sk.toTypedKey(kcert);
|
||||
c = kcert;
|
||||
} else {
|
||||
padding = null;
|
||||
}
|
||||
Destination rv;
|
||||
synchronized(_cache) {
|
||||
rv = _cache.get(sk);
|
||||
@ -67,7 +77,7 @@ public class Destination extends KeysAndCert {
|
||||
}
|
||||
//if (STATS)
|
||||
// I2PAppContext.getGlobalContext().statManager().addRateData("DestCache", 0);
|
||||
rv = new Destination(pk, sk, c);
|
||||
rv = new Destination(pk, sk, c, padding);
|
||||
_cache.put(sk, rv);
|
||||
}
|
||||
return rv;
|
||||
@ -86,10 +96,11 @@ public class Destination extends KeysAndCert {
|
||||
/**
|
||||
* @since 0.9.9
|
||||
*/
|
||||
private Destination(PublicKey pk, SigningPublicKey sk, Certificate c) {
|
||||
private Destination(PublicKey pk, SigningPublicKey sk, Certificate c, byte[] padding) {
|
||||
_publicKey = pk;
|
||||
_signingKey = sk;
|
||||
_certificate = c;
|
||||
_padding = padding;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,7 +149,16 @@ public class Destination extends KeysAndCert {
|
||||
****/
|
||||
|
||||
public int size() {
|
||||
return PublicKey.KEYSIZE_BYTES + _signingKey.length() + _certificate.size();
|
||||
int rv = PublicKey.KEYSIZE_BYTES + _signingKey.length();
|
||||
if (_certificate.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
|
||||
// cert data included in keys
|
||||
rv += 7;
|
||||
if (_padding != null)
|
||||
rv += _padding.length;
|
||||
} else {
|
||||
rv += _certificate.size();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user