forked from I2P_Developers/i2p.i2p
Tools: Export private key from private key file in X.509 form
Add missing loadprivatekey command to CertUtil
This commit is contained in:
@ -40,6 +40,7 @@ import javax.security.auth.x500.X500Principal;
|
|||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.data.SigningPrivateKey;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.FileSuffixFilter;
|
import net.i2p.util.FileSuffixFilter;
|
||||||
import net.i2p.util.SecureFileOutputStream;
|
import net.i2p.util.SecureFileOutputStream;
|
||||||
@ -583,6 +584,10 @@ public final class CertUtil {
|
|||||||
Certificate cert = loadCert(f);
|
Certificate cert = loadCert(f);
|
||||||
boolean rv = isRevoked(I2PAppContext.getGlobalContext(), cert);
|
boolean rv = isRevoked(I2PAppContext.getGlobalContext(), cert);
|
||||||
System.out.println("Revoked? " + rv);
|
System.out.println("Revoked? " + rv);
|
||||||
|
} else if (args[0].equals("loadprivatekey")) {
|
||||||
|
PrivateKey priv = loadPrivateKey(new FileInputStream(f));
|
||||||
|
SigningPrivateKey spk = SigUtil.fromJavaKey(priv);
|
||||||
|
System.out.println("Found private key: " + spk);
|
||||||
} else if (args[0].equals("checkall")) {
|
} else if (args[0].equals("checkall")) {
|
||||||
int rv = checkAll(f);
|
int rv = checkAll(f);
|
||||||
//System.exit(rv);
|
//System.exit(rv);
|
||||||
|
@ -157,6 +157,23 @@ public final class SelfSignedGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a self-signed certificate for the existing private key.
|
||||||
|
*
|
||||||
|
* @param cname the common name, non-null. Must be a hostname or email address. IP addresses will not be correctly encoded.
|
||||||
|
* @return self-signed certificate
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public static X509Certificate generate(SigningPrivateKey priv, String cname,
|
||||||
|
int validDays) throws GeneralSecurityException {
|
||||||
|
SigningPublicKey pub = priv.toPublic();
|
||||||
|
PublicKey jpub = SigUtil.toJavaKey(pub);
|
||||||
|
PrivateKey jpriv = SigUtil.toJavaKey(priv);
|
||||||
|
SigType type = priv.getType();
|
||||||
|
Object[] o = generate(jpub, jpriv, priv, type, cname, null, null, null, null, null, null, validDays);
|
||||||
|
return (X509Certificate) o[2];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param cname the common name, non-null. Must be a hostname or email address. IP addresses will not be correctly encoded.
|
* @param cname the common name, non-null. Must be a hostname or email address. IP addresses will not be correctly encoded.
|
||||||
* @param altNames the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses.
|
* @param altNames the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses.
|
||||||
|
@ -5,12 +5,14 @@ import java.io.BufferedInputStream;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -29,12 +31,15 @@ import net.i2p.client.I2PSession;
|
|||||||
import net.i2p.client.I2PSessionException;
|
import net.i2p.client.I2PSessionException;
|
||||||
import net.i2p.client.naming.HostTxtEntry;
|
import net.i2p.client.naming.HostTxtEntry;
|
||||||
import net.i2p.crypto.Blinding;
|
import net.i2p.crypto.Blinding;
|
||||||
|
import net.i2p.crypto.CertUtil;
|
||||||
import net.i2p.crypto.DSAEngine;
|
import net.i2p.crypto.DSAEngine;
|
||||||
import net.i2p.crypto.EncType;
|
import net.i2p.crypto.EncType;
|
||||||
import net.i2p.crypto.KeyGenerator;
|
import net.i2p.crypto.KeyGenerator;
|
||||||
import net.i2p.crypto.KeyPair;
|
import net.i2p.crypto.KeyPair;
|
||||||
|
import net.i2p.crypto.SelfSignedGenerator;
|
||||||
import net.i2p.crypto.SigAlgo;
|
import net.i2p.crypto.SigAlgo;
|
||||||
import net.i2p.crypto.SigType;
|
import net.i2p.crypto.SigType;
|
||||||
|
import net.i2p.crypto.SigUtil;
|
||||||
import net.i2p.util.OrderedProperties;
|
import net.i2p.util.OrderedProperties;
|
||||||
import net.i2p.util.RandomSource;
|
import net.i2p.util.RandomSource;
|
||||||
import net.i2p.util.SecureFileOutputStream;
|
import net.i2p.util.SecureFileOutputStream;
|
||||||
@ -101,10 +106,11 @@ public class PrivateKeyFile {
|
|||||||
String signer = null;
|
String signer = null;
|
||||||
String signername = null;
|
String signername = null;
|
||||||
String signaction = null;
|
String signaction = null;
|
||||||
|
String certfile = null;
|
||||||
int days = 365;
|
int days = 365;
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
boolean error = false;
|
boolean error = false;
|
||||||
Getopt g = new Getopt("pkf", args, "t:nuxhse:c:a:o:d:r:p:b:y:z:");
|
Getopt g = new Getopt("pkf", args, "t:nuxhse:c:a:o:d:r:p:b:y:z:w:");
|
||||||
int c;
|
int c;
|
||||||
while ((c = g.getopt()) != -1) {
|
while ((c = g.getopt()) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@ -143,6 +149,14 @@ public class PrivateKeyFile {
|
|||||||
signername = g.getOptarg();
|
signername = g.getOptarg();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
certfile = g.getOptarg();
|
||||||
|
if (mode == 0)
|
||||||
|
mode = c;
|
||||||
|
else
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'y':
|
case 'y':
|
||||||
signer = g.getOptarg();
|
signer = g.getOptarg();
|
||||||
break;
|
break;
|
||||||
@ -348,6 +362,36 @@ public class PrivateKeyFile {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
{
|
||||||
|
if (pkf.isOffline()) {
|
||||||
|
System.out.println("Private key is offline, not present in file, export failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OutputStream out = null;
|
||||||
|
try {
|
||||||
|
SigningPrivateKey priv = pkf.getSigningPrivKey();
|
||||||
|
java.security.PrivateKey jpriv = SigUtil.toJavaKey(priv);
|
||||||
|
if (signername == null)
|
||||||
|
signername = "example.i2p";
|
||||||
|
X509Certificate cert = SelfSignedGenerator.generate(priv, signername, days);
|
||||||
|
java.security.cert.Certificate[] certs = { cert };
|
||||||
|
out = new FileOutputStream(certfile);
|
||||||
|
CertUtil.exportPrivateKey(jpriv, certs, out);
|
||||||
|
System.out.println("Private key and self-signed certificate exported to " + certfile);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
System.out.println("Private key export failed");
|
||||||
|
ioe.printStackTrace();
|
||||||
|
} catch (GeneralSecurityException gse) {
|
||||||
|
System.out.println("Private key export failed");
|
||||||
|
gse.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
usage();
|
usage();
|
||||||
@ -359,9 +403,13 @@ public class PrivateKeyFile {
|
|||||||
verifySignature(pkf.getDestination());
|
verifySignature(pkf.getDestination());
|
||||||
}
|
}
|
||||||
} catch (I2PException e) {
|
} catch (I2PException e) {
|
||||||
|
String orig = offline != null ? offline : filearg;
|
||||||
|
System.out.println("Error processing file: " + orig);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
String orig = offline != null ? offline : filearg;
|
||||||
|
System.out.println("Error processing file: " + orig);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
@ -385,6 +433,7 @@ public class PrivateKeyFile {
|
|||||||
" -p enctype (specify enc type of destination)\n" +
|
" -p enctype (specify enc type of destination)\n" +
|
||||||
" -r sigtype (specify sig type of transient key, default Ed25519)\n" +
|
" -r sigtype (specify sig type of transient key, default Ed25519)\n" +
|
||||||
" -t sigtype (changes to KeyCertificate of the given sig type)\n" +
|
" -t sigtype (changes to KeyCertificate of the given sig type)\n" +
|
||||||
|
" -w file.key (export the private signing key to the file specified, also uses -d and -b options)\n" +
|
||||||
" -y 2lddestfile (sign the authentication string with the 2LD key file specified)\n" +
|
" -y 2lddestfile (sign the authentication string with the 2LD key file specified)\n" +
|
||||||
" -z signaction (authentication string command, must be \"addsubdomain\"\n" +
|
" -z signaction (authentication string command, must be \"addsubdomain\"\n" +
|
||||||
"");
|
"");
|
||||||
@ -941,8 +990,8 @@ public class PrivateKeyFile {
|
|||||||
s.append(_transientSigningPrivKey);
|
s.append(_transientSigningPrivKey);
|
||||||
} else {
|
} else {
|
||||||
s.append(this.signingPrivKey);
|
s.append(this.signingPrivKey);
|
||||||
s.append("\n");
|
|
||||||
}
|
}
|
||||||
|
s.append("\n");
|
||||||
return s.toString();
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user