- DSAEngine: Implement raw ECDSA sign/verify

- SU3File: Implement keygen
This commit is contained in:
zzz
2013-09-07 19:37:02 +00:00
parent c4f97ed65e
commit 38ec55bc72
2 changed files with 135 additions and 16 deletions

View File

@ -170,9 +170,8 @@ public class DSAEngine {
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " sig=" + type);
if (type == SigType.DSA_SHA1)
return verifySig(signature, hash, verifyingKey);
// FIXME hash of hash
try {
return altVerifySig(signature, hash.getData(), verifyingKey);
return altVerifySigRaw(signature, hash, verifyingKey);
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(type + " Sig Verify Fail", gse);
@ -325,9 +324,8 @@ public class DSAEngine {
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
if (type == SigType.DSA_SHA1)
return signIt(hash, signingKey);
// FIXME hash of hash
try {
return altSign(hash.getData(), signingKey);
return altSignRaw(hash, signingKey);
} catch (GeneralSecurityException gse) {
if (_log.shouldLog(Log.WARN))
_log.warn(type + " Sign Fail", gse);
@ -472,6 +470,30 @@ public class DSAEngine {
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.
* @throws GeneralSecurityException if algorithm unvailable or on other errors
@ -513,6 +535,27 @@ public class DSAEngine {
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.
* @throws GeneralSecurityException if algorithm unvailable or on other errors

View File

@ -14,6 +14,7 @@ import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import net.i2p.I2PAppContext;
@ -218,6 +219,7 @@ public class SU3File {
OutputStream out = null;
boolean rv = false;
try {
////// fixme NPE we don't know the type yet
MessageDigest md = _sigType.getDigestInstance();
in = new DigestInputStream(new BufferedInputStream(new FileInputStream(_file)), md);
if (!_headerVerified)
@ -357,6 +359,11 @@ public class SU3File {
ok = signCLI(args[1], args[2], args[3], args[4], args[5]);
} else if ("verifysig".equals(args[0])) {
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 {
showUsageCLI();
}
@ -368,9 +375,10 @@ public class SU3File {
}
private static final void showUsageCLI() {
System.err.println("Usage: 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 verifysig 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 verifysig signedFile.su3");
System.err.println(dumpSigTypes());
}
@ -387,6 +395,24 @@ public class SU3File {
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 */
private static final boolean showVersionCLI(String signedFile) {
try {
@ -422,15 +448,7 @@ public class SU3File {
*/
private static final boolean signCLI(String stype, String inputFile, String signedFile,
String privateKeyFile, String version, String signerName) {
SigType type = null;
try {
type = SigType.valueOf(stype);
} catch (IllegalArgumentException iae) {
try {
int code = Integer.parseInt(stype);
type = SigType.getByCode(code);
} catch (NumberFormatException nfe) {}
}
SigType type = parseSigType(stype);
if (type == null) {
System.out.println("Signature type " + stype + " is not supported");
return false;
@ -472,6 +490,7 @@ public class SU3File {
InputStream in = null;
try {
SU3File file = new SU3File(signedFile);
//// fixme
boolean isValidSignature = file.verifyAndMigrate(new File("/dev/null"));
if (isValidSignature)
System.out.println("Signature VALID (signed by " + file.getSignerString() + ')');
@ -484,4 +503,61 @@ public class SU3File {
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;
}
}