v0.3.10
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
__tinyencrypt_config.json
|
||||||
out/
|
out/
|
||||||
build
|
build
|
||||||
classes
|
classes
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ public class TinyEncryptArgs {
|
|||||||
@CommandLine.Option(names = {"--init-config"}, description = "Init encrypt config")
|
@CommandLine.Option(names = {"--init-config"}, description = "Init encrypt config")
|
||||||
boolean doInitConfig = false;
|
boolean doInitConfig = false;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--encrypt-config-local-private-key"}, description = "Do encrypt config local private key")
|
||||||
|
boolean doEncryptConfigLocalPrivateKey = false;
|
||||||
|
|
||||||
@CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "Display a help message")
|
@CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "Display a help message")
|
||||||
boolean helpRequested = false;
|
boolean helpRequested = false;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package me.hatter.tools.tinyencrypt;
|
||||||
|
|
||||||
|
import me.hatter.tools.commons.io.RFile;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
|
||||||
|
public class TinyEncryptArgsUtil {
|
||||||
|
private static final String DEFAULT_TINY_ENCRYPT_CONFIG = "~/.tinyencrypt_config.json";
|
||||||
|
|
||||||
|
|
||||||
|
public static TinyEncryptArgs parseTinyEncryptArgs(String[] args) {
|
||||||
|
TinyEncryptArgs tinyEncryptArgs = new TinyEncryptArgs();
|
||||||
|
CommandLine cmd = new CommandLine(tinyEncryptArgs);
|
||||||
|
cmd.parseArgs(args);
|
||||||
|
|
||||||
|
if (cmd.isUsageHelpRequested()) {
|
||||||
|
cmd.usage(cmd.getOut());
|
||||||
|
return null;
|
||||||
|
} else if (cmd.isVersionHelpRequested()) {
|
||||||
|
cmd.printVersionHelp(cmd.getOut());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return tinyEncryptArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RFile getTinyEncryptConfigRFile(TinyEncryptArgs tinyEncryptArgs) {
|
||||||
|
if (tinyEncryptArgs.config != null) {
|
||||||
|
return RFile.from(tinyEncryptArgs.config);
|
||||||
|
} else {
|
||||||
|
return RFile.from(DEFAULT_TINY_ENCRYPT_CONFIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,10 +9,13 @@ import me.hatter.tools.commons.log.LogConfig;
|
|||||||
import me.hatter.tools.commons.log.LogTool;
|
import me.hatter.tools.commons.log.LogTool;
|
||||||
import me.hatter.tools.commons.log.LogTools;
|
import me.hatter.tools.commons.log.LogTools;
|
||||||
import me.hatter.tools.commons.security.bc.BCUtil;
|
import me.hatter.tools.commons.security.bc.BCUtil;
|
||||||
|
import me.hatter.tools.commons.security.crypt.AESCryptTool;
|
||||||
import me.hatter.tools.commons.security.digest.Digests;
|
import me.hatter.tools.commons.security.digest.Digests;
|
||||||
import me.hatter.tools.commons.security.key.KeyPairTool;
|
import me.hatter.tools.commons.security.key.KeyPairTool;
|
||||||
import me.hatter.tools.commons.security.key.KeyUtil;
|
import me.hatter.tools.commons.security.key.KeyUtil;
|
||||||
import me.hatter.tools.commons.security.key.PKType;
|
import me.hatter.tools.commons.security.key.PKType;
|
||||||
|
import me.hatter.tools.commons.security.random.RandomTool;
|
||||||
|
import me.hatter.tools.commons.string.JSONUtil;
|
||||||
import me.hatter.tools.commons.string.StringUtil;
|
import me.hatter.tools.commons.string.StringUtil;
|
||||||
import me.hatter.tools.commons.tlv.Tlv;
|
import me.hatter.tools.commons.tlv.Tlv;
|
||||||
import me.hatter.tools.commons.tlv.TlvUtil;
|
import me.hatter.tools.commons.tlv.TlvUtil;
|
||||||
@@ -20,15 +23,15 @@ import me.hatter.tools.tinyencrypt.config.TinyEncryptConfig;
|
|||||||
import me.hatter.tools.tinyencrypt.config.TinyEncryptConstant;
|
import me.hatter.tools.tinyencrypt.config.TinyEncryptConstant;
|
||||||
import me.hatter.tools.tinyencrypt.encrypt.EncryptedFileUtil;
|
import me.hatter.tools.tinyencrypt.encrypt.EncryptedFileUtil;
|
||||||
import me.hatter.tools.tinyencrypt.encrypt.TinyEncryptMeta;
|
import me.hatter.tools.tinyencrypt.encrypt.TinyEncryptMeta;
|
||||||
import picocli.CommandLine;
|
import me.hatter.tools.tinyencrypt.util.CardCliUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class TinyEncryptMain {
|
public class TinyEncryptMain {
|
||||||
private static final String DEFAULT_TINY_ENCRYPT_CONFIG = "~/.tinyencrypt_config.json";
|
|
||||||
private static final LogTool log;
|
private static final LogTool log;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -36,19 +39,34 @@ public class TinyEncryptMain {
|
|||||||
log = LogTools.getLogTool(TinyEncryptMain.class);
|
log = LogTools.getLogTool(TinyEncryptMain.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TinyEncryptArgs parseTinyEncryptArgs(String[] args) {
|
private static void doEncryptConfigLocalPrivateKey(TinyEncryptArgs tinyEncryptArgs) {
|
||||||
TinyEncryptArgs tinyEncryptArgs = new TinyEncryptArgs();
|
TinyEncryptConfig config = TinyEncryptMainUtil.loadTinyEncryptConfig(tinyEncryptArgs);
|
||||||
CommandLine cmd = new CommandLine(tinyEncryptArgs);
|
if (config == null) {
|
||||||
cmd.parseArgs(args);
|
return;
|
||||||
|
|
||||||
if (cmd.isUsageHelpRequested()) {
|
|
||||||
cmd.usage(cmd.getOut());
|
|
||||||
return null;
|
|
||||||
} else if (cmd.isVersionHelpRequested()) {
|
|
||||||
cmd.printVersionHelp(cmd.getOut());
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return tinyEncryptArgs;
|
if (StringUtil.isEmpty(config.getLocalPrivateKeyPem())) {
|
||||||
|
log.error("Local private key pem is empty!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtil.isNotEmpty(config.getLocalPrivateKeyPemEncrypted())
|
||||||
|
|| StringUtil.isNotEmpty(config.getLocalPrivateKeyPemChallenge())) {
|
||||||
|
log.error("Local private key is already encrypted!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String challenge = RandomTool.secureRandom().nextBytes(16).asHex();
|
||||||
|
Optional<byte[]> keyOpt = CardCliUtil.getChall(config.getCardCli(), challenge);
|
||||||
|
if (!keyOpt.isPresent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] key = keyOpt.get();
|
||||||
|
String localPrivateKeyPemEncrypted = AESCryptTool.gcmEncrypt(key).from(Bytes.from(config.getLocalPrivateKeyPem())).toBytes().asBase64();
|
||||||
|
|
||||||
|
RFile tinyEncryptConfigRFile = TinyEncryptArgsUtil.getTinyEncryptConfigRFile(tinyEncryptArgs);
|
||||||
|
config.setLocalPrivateKeyPem(null);
|
||||||
|
config.setLocalPrivateKeyPemChallenge(challenge);
|
||||||
|
config.setLocalPrivateKeyPemEncrypted(localPrivateKeyPemEncrypted);
|
||||||
|
tinyEncryptConfigRFile.write(JSONUtil.pretty(config));
|
||||||
|
log.info("Write file success: " + tinyEncryptConfigRFile.file());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void doInitConfig(TinyEncryptArgs tinyEncryptArgs) {
|
private static void doInitConfig(TinyEncryptArgs tinyEncryptArgs) {
|
||||||
@@ -56,12 +74,7 @@ public class TinyEncryptMain {
|
|||||||
log.error("Default key is not assigned");
|
log.error("Default key is not assigned");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RFile writeTinyEncryptConfigRFile;
|
RFile writeTinyEncryptConfigRFile = TinyEncryptArgsUtil.getTinyEncryptConfigRFile(tinyEncryptArgs);
|
||||||
if (tinyEncryptArgs.config != null) {
|
|
||||||
writeTinyEncryptConfigRFile = RFile.from(tinyEncryptArgs.config);
|
|
||||||
} else {
|
|
||||||
writeTinyEncryptConfigRFile = RFile.from(DEFAULT_TINY_ENCRYPT_CONFIG);
|
|
||||||
}
|
|
||||||
if (writeTinyEncryptConfigRFile.exists()) {
|
if (writeTinyEncryptConfigRFile.exists()) {
|
||||||
log.error("File exists: " + tinyEncryptArgs.config);
|
log.error("File exists: " + tinyEncryptArgs.config);
|
||||||
return;
|
return;
|
||||||
@@ -134,27 +147,8 @@ public class TinyEncryptMain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TinyEncryptConfig loadTinyEncryptConfig(TinyEncryptArgs tinyEncryptArgs) {
|
|
||||||
TinyEncryptConfig config;
|
|
||||||
if (tinyEncryptArgs.config != null) {
|
|
||||||
config = RFile.from(tinyEncryptArgs.config).parseJSONObject(TinyEncryptConfig.class);
|
|
||||||
} else {
|
|
||||||
RFile defaultTinyEncryptConfigFile = RFile.from(DEFAULT_TINY_ENCRYPT_CONFIG);
|
|
||||||
if (defaultTinyEncryptConfigFile.notExists()) {
|
|
||||||
log.error("Config file not assigned, and no default config file: " + DEFAULT_TINY_ENCRYPT_CONFIG);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
config = defaultTinyEncryptConfigFile.parseJSONObject(TinyEncryptConfig.class);
|
|
||||||
}
|
|
||||||
if (StringUtil.isNotBlank(tinyEncryptArgs.key)) {
|
|
||||||
log.info("Using key from args: " + tinyEncryptArgs.key);
|
|
||||||
config.setDefaultKeyName(tinyEncryptArgs.key);
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
TinyEncryptArgs tinyEncryptArgs = parseTinyEncryptArgs(args);
|
TinyEncryptArgs tinyEncryptArgs = TinyEncryptArgsUtil.parseTinyEncryptArgs(args);
|
||||||
if (tinyEncryptArgs == null) {
|
if (tinyEncryptArgs == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -164,6 +158,10 @@ public class TinyEncryptMain {
|
|||||||
doInitConfig(tinyEncryptArgs);
|
doInitConfig(tinyEncryptArgs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (tinyEncryptArgs.doEncryptConfigLocalPrivateKey) { // --encrypt-config-local-private-key
|
||||||
|
doEncryptConfigLocalPrivateKey(tinyEncryptArgs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (tinyEncryptArgs.fileInfo) { // --info
|
if (tinyEncryptArgs.fileInfo) { // --info
|
||||||
fileInfo(tinyEncryptArgs);
|
fileInfo(tinyEncryptArgs);
|
||||||
return;
|
return;
|
||||||
@@ -181,7 +179,7 @@ public class TinyEncryptMain {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyEncryptConfig config = loadTinyEncryptConfig(tinyEncryptArgs);
|
TinyEncryptConfig config = TinyEncryptMainUtil.loadTinyEncryptConfig(tinyEncryptArgs);
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -236,8 +234,10 @@ public class TinyEncryptMain {
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
} catch (JumpOutException joe) {
|
} catch (JumpOutException joe) {
|
||||||
log.error(joe.getMessage());
|
if (StringUtil.isNotEmpty(joe.getMessage())) {
|
||||||
log.debug(joe.getMessage(), joe);
|
log.error(joe.getMessage());
|
||||||
|
log.debug(joe.getMessage(), joe);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package me.hatter.tools.tinyencrypt;
|
||||||
|
|
||||||
|
import me.hatter.tools.commons.io.RFile;
|
||||||
|
import me.hatter.tools.commons.log.LogTool;
|
||||||
|
import me.hatter.tools.commons.log.LogTools;
|
||||||
|
import me.hatter.tools.commons.string.StringUtil;
|
||||||
|
import me.hatter.tools.tinyencrypt.config.TinyEncryptConfig;
|
||||||
|
|
||||||
|
public class TinyEncryptMainUtil {
|
||||||
|
private static final LogTool log = LogTools.getLogTool(TinyEncryptMainUtil.class);
|
||||||
|
|
||||||
|
public static TinyEncryptConfig loadTinyEncryptConfig(TinyEncryptArgs tinyEncryptArgs) {
|
||||||
|
RFile tinyEncryptConfigRFile = TinyEncryptArgsUtil.getTinyEncryptConfigRFile(tinyEncryptArgs);
|
||||||
|
if (tinyEncryptConfigRFile.notExists()) {
|
||||||
|
log.error("Config file not found: " + tinyEncryptConfigRFile.file());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
TinyEncryptConfig config = tinyEncryptConfigRFile.parseJSONObject(TinyEncryptConfig.class);
|
||||||
|
if (StringUtil.isNotBlank(tinyEncryptArgs.key)) {
|
||||||
|
log.info("Using key from args: " + tinyEncryptArgs.key);
|
||||||
|
config.setDefaultKeyName(tinyEncryptArgs.key);
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,17 @@
|
|||||||
package me.hatter.tools.tinyencrypt.config;
|
package me.hatter.tools.tinyencrypt.config;
|
||||||
|
|
||||||
|
import me.hatter.tools.commons.string.StringUtil;
|
||||||
|
|
||||||
public class TinyEncryptConfig {
|
public class TinyEncryptConfig {
|
||||||
private String defaultKeyName;
|
private String defaultKeyName;
|
||||||
private String localPublicKeyPem;
|
private String localPublicKeyPem;
|
||||||
private String localPrivateKeyPem;
|
private String localPrivateKeyPem;
|
||||||
|
private String localPrivateKeyPemEncrypted;
|
||||||
|
private String localPrivateKeyPemChallenge;
|
||||||
private String pgpEncryptPublicKeyPem;
|
private String pgpEncryptPublicKeyPem;
|
||||||
|
@Deprecated
|
||||||
private String pgpDecryptCmd;
|
private String pgpDecryptCmd;
|
||||||
|
private String cardCli;
|
||||||
|
|
||||||
public String getDefaultKeyName() {
|
public String getDefaultKeyName() {
|
||||||
return defaultKeyName;
|
return defaultKeyName;
|
||||||
@@ -31,6 +37,22 @@ public class TinyEncryptConfig {
|
|||||||
this.localPrivateKeyPem = localPrivateKeyPem;
|
this.localPrivateKeyPem = localPrivateKeyPem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLocalPrivateKeyPemEncrypted() {
|
||||||
|
return localPrivateKeyPemEncrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalPrivateKeyPemEncrypted(String localPrivateKeyPemEncrypted) {
|
||||||
|
this.localPrivateKeyPemEncrypted = localPrivateKeyPemEncrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalPrivateKeyPemChallenge() {
|
||||||
|
return localPrivateKeyPemChallenge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalPrivateKeyPemChallenge(String localPrivateKeyPemChallenge) {
|
||||||
|
this.localPrivateKeyPemChallenge = localPrivateKeyPemChallenge;
|
||||||
|
}
|
||||||
|
|
||||||
public String getPgpEncryptPublicKeyPem() {
|
public String getPgpEncryptPublicKeyPem() {
|
||||||
return pgpEncryptPublicKeyPem;
|
return pgpEncryptPublicKeyPem;
|
||||||
}
|
}
|
||||||
@@ -46,4 +68,12 @@ public class TinyEncryptConfig {
|
|||||||
public void setPgpDecryptCmd(String pgpDecryptCmd) {
|
public void setPgpDecryptCmd(String pgpDecryptCmd) {
|
||||||
this.pgpDecryptCmd = pgpDecryptCmd;
|
this.pgpDecryptCmd = pgpDecryptCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCardCli() {
|
||||||
|
return StringUtil.def(cardCli, pgpDecryptCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCardCli(String cardCli) {
|
||||||
|
this.cardCli = cardCli;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package me.hatter.tools.tinyencrypt.config;
|
package me.hatter.tools.tinyencrypt.config;
|
||||||
|
|
||||||
public class TinyEncryptConstant {
|
public class TinyEncryptConstant {
|
||||||
public static final String VERSION = "0.3.9";
|
public static final String VERSION = "0.3.10";
|
||||||
|
|
||||||
public static final String ENC_FILE_EXT = ".tinyenc";
|
public static final String ENC_FILE_EXT = ".tinyenc";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package me.hatter.tools.tinyencrypt.encrypt;
|
package me.hatter.tools.tinyencrypt.encrypt;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import me.hatter.tools.commons.assertion.AssertUtil;
|
import me.hatter.tools.commons.assertion.AssertUtil;
|
||||||
import me.hatter.tools.commons.bytes.Bytes;
|
import me.hatter.tools.commons.bytes.Bytes;
|
||||||
import me.hatter.tools.commons.io.DefaultRollCounter;
|
import me.hatter.tools.commons.io.DefaultRollCounter;
|
||||||
@@ -18,11 +16,13 @@ import me.hatter.tools.commons.tlv.Tlv;
|
|||||||
import me.hatter.tools.commons.tlv.TlvUtil;
|
import me.hatter.tools.commons.tlv.TlvUtil;
|
||||||
import me.hatter.tools.tinyencrypt.config.TinyEncryptConfig;
|
import me.hatter.tools.tinyencrypt.config.TinyEncryptConfig;
|
||||||
import me.hatter.tools.tinyencrypt.config.TinyEncryptConstant;
|
import me.hatter.tools.tinyencrypt.config.TinyEncryptConstant;
|
||||||
|
import me.hatter.tools.tinyencrypt.util.CardCliUtil;
|
||||||
import me.hatter.tools.tinyencrypt.util.NilOutputStream;
|
import me.hatter.tools.tinyencrypt.util.NilOutputStream;
|
||||||
import me.hatter.tools.tinyencrypt.util.SwingWindow;
|
import me.hatter.tools.tinyencrypt.util.SwingWindow;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
@@ -45,44 +45,25 @@ public class EncryptedFileUtil {
|
|||||||
log.error("File is not encrypted with PGP envelop");
|
log.error("File is not encrypted with PGP envelop");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (StringUtil.isBlank(config.getPgpDecryptCmd())) {
|
if (StringUtil.isBlank(config.getCardCli())) {
|
||||||
log.error("PGP decrypt cmd is not configed");
|
log.error("Card-cli is empty!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (RFile.from(config.getPgpDecryptCmd()).isNotFile()) {
|
if (RFile.from(config.getCardCli()).isNotFile()) {
|
||||||
log.error("PGP decrypt cmd is miss configed");
|
log.error("PGP decrypt cmd is miss configed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
System.out.print("Input PGP PIN: ");
|
Optional<String> pinOpt = CardCliUtil.readUserPin();
|
||||||
char[] pin = System.console().readPassword();
|
if (!pinOpt.isPresent()) {
|
||||||
if (pin.length < 6) {
|
|
||||||
log.error("PIN must have 6 letters");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ProcessBuilder pb = new ProcessBuilder(
|
String pin = pinOpt.get();
|
||||||
config.getPgpDecryptCmd(),
|
Optional<byte[]> dataKeyOpt = CardCliUtil.decryptPgpEnvelop(
|
||||||
"pgp-card-decrypt",
|
config.getCardCli(), pin, meta.getPgpEnvelop());
|
||||||
"--cipher-base64", meta.getPgpEnvelop(),
|
if (!dataKeyOpt.isPresent()) {
|
||||||
"--pass", new String(pin),
|
|
||||||
"--json");
|
|
||||||
log.info("Start: " + config.getPgpDecryptCmd());
|
|
||||||
log.debug("Start process: " + pb.command());
|
|
||||||
Process p = pb.start();
|
|
||||||
p.waitFor();
|
|
||||||
log.info("Finished command");
|
|
||||||
try {
|
|
||||||
byte[] jsonBytes = IOUtil.readToBytes(p.getInputStream());
|
|
||||||
String jsonStr = new String(jsonBytes, StandardCharsets.UTF_8);
|
|
||||||
if (log.isDebugEnable()) {
|
|
||||||
log.debug("Read cmd JSON: " + jsonStr);
|
|
||||||
}
|
|
||||||
JSONObject jo = JSON.parseObject(jsonStr);
|
|
||||||
dataKey = Bytes.fromHex(jo.getString("text_hex")).bytes();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error in parse pgp-card-decrypt: " + e, e);
|
|
||||||
log.error("err out: " + Bytes.from(IOUtil.readToBytes(p.getErrorStream())));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
dataKey = dataKeyOpt.get();
|
||||||
} else {
|
} else {
|
||||||
dataKey = TinyEncryptMetaUtil.decryptDataKey(config, meta);
|
dataKey = TinyEncryptMetaUtil.decryptDataKey(config, meta);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import me.hatter.tools.commons.log.LogTool;
|
|||||||
import me.hatter.tools.commons.log.LogTools;
|
import me.hatter.tools.commons.log.LogTools;
|
||||||
import me.hatter.tools.commons.network.HttpRequest;
|
import me.hatter.tools.commons.network.HttpRequest;
|
||||||
import me.hatter.tools.commons.os.OSUtil;
|
import me.hatter.tools.commons.os.OSUtil;
|
||||||
|
import me.hatter.tools.commons.security.crypt.AESCryptTool;
|
||||||
import me.hatter.tools.commons.security.digest.Digests;
|
import me.hatter.tools.commons.security.digest.Digests;
|
||||||
import me.hatter.tools.commons.security.key.KeyUtil;
|
import me.hatter.tools.commons.security.key.KeyUtil;
|
||||||
import me.hatter.tools.commons.security.random.RandomTool;
|
import me.hatter.tools.commons.security.random.RandomTool;
|
||||||
@@ -16,6 +17,7 @@ import me.hatter.tools.commons.security.sign.Signatures;
|
|||||||
import me.hatter.tools.commons.string.StringUtil;
|
import me.hatter.tools.commons.string.StringUtil;
|
||||||
import me.hatter.tools.tinyencrypt.config.TinyEncryptConfig;
|
import me.hatter.tools.tinyencrypt.config.TinyEncryptConfig;
|
||||||
import me.hatter.tools.tinyencrypt.config.TinyEncryptConstant;
|
import me.hatter.tools.tinyencrypt.config.TinyEncryptConstant;
|
||||||
|
import me.hatter.tools.tinyencrypt.util.CardCliUtil;
|
||||||
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
@@ -23,6 +25,7 @@ import java.security.interfaces.RSAPublicKey;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class TinyEncryptMetaUtil {
|
public class TinyEncryptMetaUtil {
|
||||||
private static final LogTool log = LogTools.getLogTool(TinyEncryptMetaUtil.class);
|
private static final LogTool log = LogTools.getLogTool(TinyEncryptMetaUtil.class);
|
||||||
@@ -37,7 +40,27 @@ public class TinyEncryptMetaUtil {
|
|||||||
return JSON.parseObject(meta, TinyEncryptMeta.class);
|
return JSON.parseObject(meta, TinyEncryptMeta.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void requireLocalPrivateKeyPem(TinyEncryptConfig config) {
|
||||||
|
if (StringUtil.isNotEmpty(config.getLocalPrivateKeyPem())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtil.isEmpty(config.getLocalPrivateKeyPemChallenge())
|
||||||
|
|| StringUtil.isEmpty(config.getLocalPrivateKeyPemEncrypted())) {
|
||||||
|
throw new JumpOutException("Cannot prepare local private key pem!");
|
||||||
|
}
|
||||||
|
Optional<byte[]> keyOpt = CardCliUtil.getChall(config.getCardCli(), config.getLocalPrivateKeyPemChallenge());
|
||||||
|
if (!keyOpt.isPresent()) {
|
||||||
|
throw new JumpOutException();
|
||||||
|
}
|
||||||
|
byte[] key = keyOpt.get();
|
||||||
|
String localPrivateKeyPem = AESCryptTool.gcmDecrypt(key)
|
||||||
|
.from(Bytes.fromBase64(config.getLocalPrivateKeyPemEncrypted())).toBytes().string();
|
||||||
|
log.info("Decrypt local private key success!");
|
||||||
|
config.setLocalPrivateKeyPem(localPrivateKeyPem);
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] decryptDataKey(TinyEncryptConfig config, TinyEncryptMeta meta) {
|
public static byte[] decryptDataKey(TinyEncryptConfig config, TinyEncryptMeta meta) {
|
||||||
|
requireLocalPrivateKeyPem(config);
|
||||||
PrivateKey privateKey = KeyUtil.parsePrivateKeyPEM(config.getLocalPrivateKeyPem());
|
PrivateKey privateKey = KeyUtil.parsePrivateKeyPEM(config.getLocalPrivateKeyPem());
|
||||||
String envelop = meta.getEnvelop();
|
String envelop = meta.getEnvelop();
|
||||||
|
|
||||||
@@ -63,6 +86,7 @@ public class TinyEncryptMetaUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static TinyEncryptMeta create(TinyEncryptConfig config, String comment) {
|
public static TinyEncryptMeta create(TinyEncryptConfig config, String comment) {
|
||||||
|
requireLocalPrivateKeyPem(config);
|
||||||
PublicKey publicKey = KeyUtil.parsePublicKeyPEM(config.getLocalPublicKeyPem());
|
PublicKey publicKey = KeyUtil.parsePublicKeyPEM(config.getLocalPublicKeyPem());
|
||||||
PrivateKey privateKey = KeyUtil.parsePrivateKeyPEM(config.getLocalPrivateKeyPem());
|
PrivateKey privateKey = KeyUtil.parsePrivateKeyPEM(config.getLocalPrivateKeyPem());
|
||||||
PublicKey pgpEncryptPublicKey = null;
|
PublicKey pgpEncryptPublicKey = null;
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package me.hatter.tools.tinyencrypt.util;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import me.hatter.tools.commons.bytes.Bytes;
|
||||||
|
import me.hatter.tools.commons.exception.JumpOutException;
|
||||||
|
import me.hatter.tools.commons.io.IOUtil;
|
||||||
|
import me.hatter.tools.commons.log.LogTool;
|
||||||
|
import me.hatter.tools.commons.log.LogTools;
|
||||||
|
import me.hatter.tools.commons.string.StringUtil;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class CardCliUtil {
|
||||||
|
private static final LogTool log = LogTools.getLogTool(CardCliUtil.class);
|
||||||
|
|
||||||
|
public static Optional<String> readUserPin() {
|
||||||
|
System.out.print("Input PGP user PIN: ");
|
||||||
|
char[] pin = System.console().readPassword();
|
||||||
|
if (pin.length < 6) {
|
||||||
|
log.error("User PIN must have 6 letters");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
return Optional.of(new String(pin));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<byte[]> getChall(String cardCli, String challenge) {
|
||||||
|
if (StringUtil.isEmpty(cardCli)) {
|
||||||
|
throw new JumpOutException("Card-cli is empty!");
|
||||||
|
}
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
|
cardCli,
|
||||||
|
"chall",
|
||||||
|
"--challenge-hex", challenge,
|
||||||
|
"--json", "--sha256");
|
||||||
|
log.info("Start: " + cardCli);
|
||||||
|
|
||||||
|
Optional<String> outputsOpt = runProcess(pb);
|
||||||
|
if (!outputsOpt.isPresent()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
JSONObject jo = JSON.parseObject(outputsOpt.get());
|
||||||
|
return Optional.of(Bytes.fromHex(jo.getString("response_sha256_hex")).bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<byte[]> decryptPgpEnvelop(String cardCli, String pin, String pgpEnvelop) {
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
|
cardCli,
|
||||||
|
"pgp-card-decrypt",
|
||||||
|
"--cipher-base64", pgpEnvelop,
|
||||||
|
"--pin", pin,
|
||||||
|
"--json");
|
||||||
|
log.info("Start: " + cardCli);
|
||||||
|
Optional<String> outputsOpt = runProcess(pb);
|
||||||
|
if (!outputsOpt.isPresent()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
JSONObject jo = JSON.parseObject(outputsOpt.get());
|
||||||
|
return Optional.of(Bytes.fromHex(jo.getString("text_hex")).bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<String> runProcess(ProcessBuilder pb) {
|
||||||
|
Process p = null;
|
||||||
|
try {
|
||||||
|
log.debug("Start process: " + pb.command());
|
||||||
|
p = pb.start();
|
||||||
|
p.waitFor();
|
||||||
|
log.info("Finished command");
|
||||||
|
|
||||||
|
byte[] jsonBytes = IOUtil.readToBytes(p.getInputStream());
|
||||||
|
String outputs = new String(jsonBytes, StandardCharsets.UTF_8);
|
||||||
|
if (log.isDebugEnable()) {
|
||||||
|
log.debug("Read cmd outputs: " + outputs);
|
||||||
|
}
|
||||||
|
return Optional.of(outputs);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error in run card-cli: " + e, e);
|
||||||
|
if (p != null) {
|
||||||
|
log.error("err out: " + Bytes.from(IOUtil.readToBytes(p.getErrorStream())));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user