forked from I2P_Developers/i2p.i2p
- DSAEngine: Implement raw ECDSA sign/verify
- SU3File: Implement keygen
This commit is contained in:
@ -170,9 +170,8 @@ public class DSAEngine {
|
|||||||
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " sig=" + type);
|
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " sig=" + type);
|
||||||
if (type == SigType.DSA_SHA1)
|
if (type == SigType.DSA_SHA1)
|
||||||
return verifySig(signature, hash, verifyingKey);
|
return verifySig(signature, hash, verifyingKey);
|
||||||
// FIXME hash of hash
|
|
||||||
try {
|
try {
|
||||||
return altVerifySig(signature, hash.getData(), verifyingKey);
|
return altVerifySigRaw(signature, hash, verifyingKey);
|
||||||
} catch (GeneralSecurityException gse) {
|
} catch (GeneralSecurityException gse) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn(type + " Sig Verify Fail", gse);
|
_log.warn(type + " Sig Verify Fail", gse);
|
||||||
@ -325,9 +324,8 @@ public class DSAEngine {
|
|||||||
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
|
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
|
||||||
if (type == SigType.DSA_SHA1)
|
if (type == SigType.DSA_SHA1)
|
||||||
return signIt(hash, signingKey);
|
return signIt(hash, signingKey);
|
||||||
// FIXME hash of hash
|
|
||||||
try {
|
try {
|
||||||
return altSign(hash.getData(), signingKey);
|
return altSignRaw(hash, signingKey);
|
||||||
} catch (GeneralSecurityException gse) {
|
} catch (GeneralSecurityException gse) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn(type + " Sign Fail", gse);
|
_log.warn(type + " Sign Fail", gse);
|
||||||
@ -472,6 +470,30 @@ public class DSAEngine {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic raw verify ECDSA only
|
||||||
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
|
* @since 0.9.9
|
||||||
|
*/
|
||||||
|
private boolean altVerifySigRaw(Signature signature, SimpleDataStructure hash, SigningPublicKey verifyingKey)
|
||||||
|
throws GeneralSecurityException {
|
||||||
|
SigType type = signature.getType();
|
||||||
|
if (type != verifyingKey.getType())
|
||||||
|
throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
|
||||||
|
int hashlen = hash.length();
|
||||||
|
if (type.getHashLen() != hashlen)
|
||||||
|
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
|
||||||
|
if (type == SigType.DSA_SHA1)
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
|
||||||
|
java.security.Signature jsig = java.security.Signature.getInstance("NONEwithECDSA");
|
||||||
|
PublicKey pubKey = SigUtil.toJavaECKey(verifyingKey);
|
||||||
|
jsig.initVerify(pubKey);
|
||||||
|
jsig.update(hash.getData());
|
||||||
|
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alternate to verifySignature() using java.security libraries.
|
* Alternate to verifySignature() using java.security libraries.
|
||||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
@ -513,6 +535,27 @@ public class DSAEngine {
|
|||||||
return SigUtil.fromJavaSig(jsig.sign(), type);
|
return SigUtil.fromJavaSig(jsig.sign(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic raw sign ECDSA only.
|
||||||
|
* @param hash SHA1Hash, Hash, Hash384, or Hash512
|
||||||
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
|
* @since 0.9.9
|
||||||
|
*/
|
||||||
|
private Signature altSignRaw(SimpleDataStructure hash, SigningPrivateKey privateKey) throws GeneralSecurityException {
|
||||||
|
SigType type = privateKey.getType();
|
||||||
|
if (type == SigType.DSA_SHA1)
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
int hashlen = hash.length();
|
||||||
|
if (type.getHashLen() != hashlen)
|
||||||
|
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
|
||||||
|
|
||||||
|
java.security.Signature jsig = java.security.Signature.getInstance("NONEwithECDSA");
|
||||||
|
PrivateKey privKey = SigUtil.toJavaECKey(privateKey);
|
||||||
|
jsig.initSign(privKey, _context.random());
|
||||||
|
jsig.update(hash.getData());
|
||||||
|
return SigUtil.fromJavaSig(jsig.sign(), type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alternate to sign() using java.security libraries.
|
* Alternate to sign() using java.security libraries.
|
||||||
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
* @throws GeneralSecurityException if algorithm unvailable or on other errors
|
||||||
|
@ -14,6 +14,7 @@ import java.security.DigestOutputStream;
|
|||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
@ -218,6 +219,7 @@ public class SU3File {
|
|||||||
OutputStream out = null;
|
OutputStream out = null;
|
||||||
boolean rv = false;
|
boolean rv = false;
|
||||||
try {
|
try {
|
||||||
|
////// fixme NPE we don't know the type yet
|
||||||
MessageDigest md = _sigType.getDigestInstance();
|
MessageDigest md = _sigType.getDigestInstance();
|
||||||
in = new DigestInputStream(new BufferedInputStream(new FileInputStream(_file)), md);
|
in = new DigestInputStream(new BufferedInputStream(new FileInputStream(_file)), md);
|
||||||
if (!_headerVerified)
|
if (!_headerVerified)
|
||||||
@ -357,6 +359,11 @@ public class SU3File {
|
|||||||
ok = signCLI(args[1], args[2], args[3], args[4], args[5]);
|
ok = signCLI(args[1], args[2], args[3], args[4], args[5]);
|
||||||
} else if ("verifysig".equals(args[0])) {
|
} else if ("verifysig".equals(args[0])) {
|
||||||
ok = verifySigCLI(args[1]);
|
ok = verifySigCLI(args[1]);
|
||||||
|
} else if ("keygen".equals(args[0])) {
|
||||||
|
if (args[1].equals("-t"))
|
||||||
|
ok = genKeysCLI(args[2], args[3], args[4]);
|
||||||
|
else
|
||||||
|
ok = genKeysCLI(args[1], args[2]);
|
||||||
} else {
|
} else {
|
||||||
showUsageCLI();
|
showUsageCLI();
|
||||||
}
|
}
|
||||||
@ -368,7 +375,8 @@ public class SU3File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final void showUsageCLI() {
|
private static final void showUsageCLI() {
|
||||||
System.err.println("Usage: SU3File showversion signedFile.su3");
|
System.err.println("Usage: SU3File keygen [-t type|code] publicKeyFile privateKeyFile");
|
||||||
|
System.err.println(" SU3File showversion signedFile.su3");
|
||||||
System.err.println(" SU3File sign [-t type|code] inputFile.zip signedFile.su3 privateKeyFile version signerName@mail.i2p");
|
System.err.println(" SU3File sign [-t type|code] inputFile.zip signedFile.su3 privateKeyFile version signerName@mail.i2p");
|
||||||
System.err.println(" SU3File verifysig signedFile.su3");
|
System.err.println(" SU3File verifysig signedFile.su3");
|
||||||
System.err.println(dumpSigTypes());
|
System.err.println(dumpSigTypes());
|
||||||
@ -387,6 +395,24 @@ public class SU3File {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param stype number or name
|
||||||
|
* @return null if not found
|
||||||
|
* @since 0.9.9
|
||||||
|
*/
|
||||||
|
private static SigType parseSigType(String stype) {
|
||||||
|
try {
|
||||||
|
return SigType.valueOf(stype.toUpperCase(Locale.US));
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
try {
|
||||||
|
int code = Integer.parseInt(stype);
|
||||||
|
return SigType.getByCode(code);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @return success */
|
/** @return success */
|
||||||
private static final boolean showVersionCLI(String signedFile) {
|
private static final boolean showVersionCLI(String signedFile) {
|
||||||
try {
|
try {
|
||||||
@ -422,15 +448,7 @@ public class SU3File {
|
|||||||
*/
|
*/
|
||||||
private static final boolean signCLI(String stype, String inputFile, String signedFile,
|
private static final boolean signCLI(String stype, String inputFile, String signedFile,
|
||||||
String privateKeyFile, String version, String signerName) {
|
String privateKeyFile, String version, String signerName) {
|
||||||
SigType type = null;
|
SigType type = parseSigType(stype);
|
||||||
try {
|
|
||||||
type = SigType.valueOf(stype);
|
|
||||||
} catch (IllegalArgumentException iae) {
|
|
||||||
try {
|
|
||||||
int code = Integer.parseInt(stype);
|
|
||||||
type = SigType.getByCode(code);
|
|
||||||
} catch (NumberFormatException nfe) {}
|
|
||||||
}
|
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
System.out.println("Signature type " + stype + " is not supported");
|
System.out.println("Signature type " + stype + " is not supported");
|
||||||
return false;
|
return false;
|
||||||
@ -472,6 +490,7 @@ public class SU3File {
|
|||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
try {
|
try {
|
||||||
SU3File file = new SU3File(signedFile);
|
SU3File file = new SU3File(signedFile);
|
||||||
|
//// fixme
|
||||||
boolean isValidSignature = file.verifyAndMigrate(new File("/dev/null"));
|
boolean isValidSignature = file.verifyAndMigrate(new File("/dev/null"));
|
||||||
if (isValidSignature)
|
if (isValidSignature)
|
||||||
System.out.println("Signature VALID (signed by " + file.getSignerString() + ')');
|
System.out.println("Signature VALID (signed by " + file.getSignerString() + ')');
|
||||||
@ -484,4 +503,61 @@ public class SU3File {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return success
|
||||||
|
* @since 0.9.9
|
||||||
|
*/
|
||||||
|
private static final boolean genKeysCLI(String publicKeyFile, String privateKeyFile) {
|
||||||
|
return genKeysCLI(DEFAULT_TYPE, publicKeyFile, privateKeyFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return success
|
||||||
|
* @since 0.9.9
|
||||||
|
*/
|
||||||
|
private static final boolean genKeysCLI(String stype, String publicKeyFile, String privateKeyFile) {
|
||||||
|
SigType type = parseSigType(stype);
|
||||||
|
if (type == null) {
|
||||||
|
System.out.println("Signature type " + stype + " is not supported");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return genKeysCLI(type, publicKeyFile, privateKeyFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return success
|
||||||
|
* @since 0.9.9
|
||||||
|
*/
|
||||||
|
private static final boolean genKeysCLI(SigType type, String publicKeyFile, String privateKeyFile) {
|
||||||
|
FileOutputStream fileOutputStream = null;
|
||||||
|
I2PAppContext context = I2PAppContext.getGlobalContext();
|
||||||
|
try {
|
||||||
|
SimpleDataStructure signingKeypair[] = context.keyGenerator().generateSigningKeys(type);
|
||||||
|
SigningPublicKey signingPublicKey = (SigningPublicKey) signingKeypair[0];
|
||||||
|
SigningPrivateKey signingPrivateKey = (SigningPrivateKey) signingKeypair[1];
|
||||||
|
|
||||||
|
fileOutputStream = new FileOutputStream(publicKeyFile);
|
||||||
|
signingPublicKey.writeBytes(fileOutputStream);
|
||||||
|
fileOutputStream.close();
|
||||||
|
fileOutputStream = null;
|
||||||
|
|
||||||
|
fileOutputStream = new FileOutputStream(privateKeyFile);
|
||||||
|
signingPrivateKey.writeBytes(fileOutputStream);
|
||||||
|
|
||||||
|
System.out.println("\r\n" + type + " Private key written to: " + privateKeyFile);
|
||||||
|
System.out.println(type + " Public key written to: " + publicKeyFile);
|
||||||
|
System.out.println("\r\nPublic key: " + signingPublicKey.toBase64() + "\r\n");
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Error writing keys:");
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (fileOutputStream != null)
|
||||||
|
try {
|
||||||
|
fileOutputStream.close();
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user