73 lines
3.6 KiB
Java
73 lines
3.6 KiB
Java
package me.hatter.tools.tinyencrypt.util;
|
|
|
|
import me.hatter.tools.commons.assertion.AssertUtil;
|
|
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.misc.Base64s;
|
|
|
|
import java.util.Optional;
|
|
|
|
public class AgeCliUtil {
|
|
private static final LogTool log = LogTools.getLogTool(AgeCliUtil.class);
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
System.out.println(
|
|
decryptBytes("age", "age1yubikey1qtwna67eqmyu7q9s3mpf7lkkrqzdrnqazdfdjftmv2qercy0cdchc7jcpu5", "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHBpdi1wMjU2IHFNWDVVUSBBNGMwMTl3\neXhQSXQ1dnhxSzFUNk4rNlJ6QkJCcnJqazZzTVAzcS9sSktyRQpBOXNQSVFudDBQ\nd2kyMFpySGxIUS8yemVwdkJxdEpoZHl3NTJuUzFaTjJJCi0tLSBwbW45LzUyem9j\nZWpROUFRT2huVDArS2hjaWFBeVd4S0xaTzh5eFo5QlhRCo2zDaVK/7YuOShVT0iw\n43LFOEP3T9v53YKhuUqjmm+6af93U2H/ppZVZluXrYPpR6+WHL4vdxflExP4yH1e\n8C+hFKSSdvxQe7cE8lHG\n-----END AGE ENCRYPTED FILE-----", Optional.empty())
|
|
);
|
|
}
|
|
|
|
public static Optional<byte[]> decryptBytes(String ageCli, String ageRecipient, String ageEnvelop, Optional<String> serialOpt) {
|
|
AssertUtil.notEmpty(ageCli, "Age-cli cannot be empty");
|
|
AssertUtil.notEmpty(ageRecipient, "Age-recipient cannot be empty");
|
|
AssertUtil.isTrue(ageRecipient.matches("^[a-zA-Z0-9]+$"), "Age-recipient illegal");
|
|
AssertUtil.notEmpty(ageEnvelop, "Age-envelop cannot be empty");
|
|
AssertUtil.isFalse(ageEnvelop.contains("'"), "Age-envelop cannot contains `'`");
|
|
AssertUtil.isTrue(ageEnvelop.matches("^[\\-/+=\\n\\r\\sa-zA-Z0-9]+$"), "Age-envelop illegal");
|
|
|
|
final RFile recipientAgeFileWithoutSerial = RFile.fromUserHome(".tinyencrypt/" + ageRecipient + ".age");
|
|
final RFile recipientAgeFileWithSerial = serialOpt.map(s -> RFile.fromUserHome(".tinyencrypt/" + ageRecipient + ".age." + s)).orElse(null);
|
|
|
|
final RFile recipientAgeFile = ((recipientAgeFileWithSerial != null) && recipientAgeFileWithSerial.isFile())
|
|
? recipientAgeFileWithSerial : recipientAgeFileWithoutSerial;
|
|
|
|
AssertUtil.isTrue(recipientAgeFile.isFile(), "Age key file required");
|
|
|
|
final ProcessBuilder pb = new ProcessBuilder(
|
|
"sh",
|
|
"-c",
|
|
"echo '" + ageEnvelop + "' | " + ageCli + " -d -i " + recipientAgeFile.file().getAbsolutePath());
|
|
|
|
pb.redirectInput(ProcessBuilder.Redirect.PIPE);
|
|
pb.redirectError(ProcessBuilder.Redirect.PIPE);
|
|
|
|
return CardCliUtil.runProcess(pb).map(b -> Base64s.normal().decode(b.trim()));
|
|
}
|
|
|
|
public static String encryptBytes(String ageCli, String ageRecipient, byte[] bytes) {
|
|
AssertUtil.notEmpty(ageCli, "Age-cli cannot be empty");
|
|
AssertUtil.notEmpty(ageRecipient, "Age-recipient cannot be empty");
|
|
AssertUtil.notNull(bytes, "Bytes cannot be null");
|
|
final ProcessBuilder pb = new ProcessBuilder(
|
|
"sh",
|
|
"-c",
|
|
"echo " + Base64s.normal().encode(bytes) + " | " + ageCli + " -e -r " + ageRecipient + " -a");
|
|
final Optional<String> outputsOpt = CardCliUtil.runProcess(pb);
|
|
if (!outputsOpt.isPresent()) {
|
|
throw new RuntimeException("Encrypt use age failed!");
|
|
}
|
|
return outputsOpt.get();
|
|
}
|
|
|
|
|
|
public static Optional<String> readUserPin() {
|
|
System.out.print("Input PIV user PIN: ");
|
|
final 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));
|
|
}
|
|
}
|