Files
tiny-encrypt-java/src/main/java/me/hatter/tools/tinyencrypt/util/AgeCliUtil.java
2023-03-25 08:14:51 +08:00

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));
}
}