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);
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user