commit 6b6ef474a4a9fd17a1f6858e2b102c5150ccbac1
parent 35a6adb000319694245fdaadd340a929213ef2e9
Author: Wim Dupont <wim@wimdupont.com>
Date: Tue, 28 Feb 2023 21:42:06 +0100
version bump and minor updates
Diffstat:
6 files changed, 166 insertions(+), 160 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -33,3 +33,5 @@ build/
.vscode/
/src/main/resources/application.properties
+/src/main/resources/secret.asc
+/src/main/resources/totpfiles/
diff --git a/pom.xml b/pom.xml
@@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
- <groupId>com.dupont</groupId>
+ <groupId>com.wimdupont</groupId>
<artifactId>TotpGenerator</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
@@ -23,7 +23,7 @@
<dependency>
<groupId>com.github.bastiaanjansen</groupId>
<artifactId>otp-java</artifactId>
- <version>1.2.3</version>
+ <version>2.0.1</version>
</dependency>
</dependencies>
@@ -62,7 +62,7 @@
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>
- Main
+ com.wimdupont.Main
</mainClass>
</manifest>
</archive>
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
@@ -1,12 +0,0 @@
-import com.bastiaanjansen.otp.TOTPGenerator.Builder;
-import service.GpgUtil;
-
-import java.util.Date;
-
-public class Main {
- public static void main(String[] args) {
- String fileArgument = args.length > 0 ? args[0] : null;
- System.out.println(Builder.withDefaultValues(new GpgUtil().decrypt(fileArgument).orElseThrow().getBytes()).generate(new Date()));
- System.exit(0);
- }
-}
diff --git a/src/main/java/com/wimdupont/Main.java b/src/main/java/com/wimdupont/Main.java
@@ -0,0 +1,12 @@
+package com.wimdupont;
+
+import com.bastiaanjansen.otp.TOTPGenerator;
+import com.wimdupont.service.GpgUtil;
+
+public class Main {
+ public static void main(String[] args) {
+ String fileArgument = args.length > 0 ? args[0] : null;
+ System.out.println(TOTPGenerator.withDefaultValues(new GpgUtil().decrypt(fileArgument).orElseThrow().getBytes()).now());
+ System.exit(0);
+ }
+}
diff --git a/src/main/java/com/wimdupont/service/GpgUtil.java b/src/main/java/com/wimdupont/service/GpgUtil.java
@@ -0,0 +1,149 @@
+package com.wimdupont.service;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openpgp.PGPCompressedData;
+import org.bouncycastle.openpgp.PGPEncryptedData;
+import org.bouncycastle.openpgp.PGPEncryptedDataList;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPLiteralData;
+import org.bouncycastle.openpgp.PGPObjectFactory;
+import org.bouncycastle.openpgp.PGPPrivateKey;
+import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
+import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
+import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
+import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
+import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Console;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.MissingResourceException;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.stream.Collectors;
+
+public class GpgUtil {
+
+ private static String dirPath;
+ private static String secretFile;
+ private static final String GPG_EXTENSION = ".gpg";
+
+ public GpgUtil() {
+ Properties properties = loadProperties();
+ dirPath = properties.getProperty("dir.path");
+ secretFile = properties.getProperty("secret.file");
+ if (dirPath == null | secretFile == null)
+ throw new RuntimeException("Properties missing.");
+ }
+
+ public Optional<String> decrypt(String fileArgument) {
+ final Scanner scanner = new Scanner(System.in);
+ File file;
+ if (fileArgument != null) {
+ file = new File(dirPath + fileArgument + GPG_EXTENSION).getAbsoluteFile();
+ if (!file.exists()) throw new RuntimeException(String.format("File \"%s\" not found", file.getName()));
+ } else {
+ File[] files = new File(dirPath).listFiles();
+ if (files == null || files.length < 1) throw new RuntimeException(dirPath + " contains no files");
+ System.out.println("Which TOTP?");
+ String fileNames = Arrays.stream(files)
+ .filter(f -> f.getName().contains(GPG_EXTENSION))
+ .map(f -> f.getName().replace(GPG_EXTENSION, ""))
+ .collect(Collectors.joining(", "));
+ System.out.println(fileNames);
+ String fileName = scanner.nextLine();
+ file = Arrays.stream(files).filter(f -> f.getName().replace(GPG_EXTENSION, "").equals(fileName)).findAny()
+ .orElseThrow(() -> new RuntimeException("File not found"));
+ }
+
+ System.out.println("Type in GPG password.");
+ Console cons = System.console();
+ String pwd;
+ if (cons != null) {
+ pwd = new String(cons.readPassword());
+ } else {
+ System.out.println("Careful, input is not hidden");
+ pwd = scanner.nextLine();
+ }
+ try {
+ return Optional.ofNullable(decryptFile(new FileInputStream(file.getAbsolutePath()), pwd.toCharArray()));
+ } catch (IOException | PGPException e) {
+ e.printStackTrace();
+ return Optional.empty();
+ }
+ }
+
+ private Properties loadProperties() {
+ final Properties properties = new Properties();
+ InputStream is = getClass().getResourceAsStream("/application.properties");
+ try {
+ if (is == null) {
+ throw new IOException();
+ }
+ properties.load(is);
+ } catch (IOException e) {
+ throw new MissingResourceException("Missing application properties", Properties.class.getSimpleName(), "application.properties");
+ }
+ return properties;
+ }
+
+ private PGPSecretKey readSecretKeyFromCol(InputStream in, long keyId) throws IOException, PGPException {
+ in = PGPUtil.getDecoderStream(in);
+ PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(in, new BcKeyFingerprintCalculator());
+ PGPSecretKey key = pgpSec.getSecretKey(keyId);
+ if (key == null) {
+ throw new IllegalArgumentException("Can't find encryption key in key ring.");
+ }
+ return key;
+ }
+
+ private String decryptFile(InputStream in, char[] pass) throws IOException, PGPException {
+ Security.addProvider(new BouncyCastleProvider());
+ PGPSecretKey secKey;
+ in = PGPUtil.getDecoderStream(in);
+ JcaPGPObjectFactory pgpFact;
+
+ PGPObjectFactory pgpF = new PGPObjectFactory(in, new BcKeyFingerprintCalculator());
+ Object o = pgpF.nextObject();
+ PGPEncryptedDataList encList;
+ if (o instanceof PGPEncryptedDataList) {
+ encList = (PGPEncryptedDataList) o;
+ } else {
+ encList = (PGPEncryptedDataList) pgpF.nextObject();
+ }
+ Iterator<PGPEncryptedData> itt = encList.getEncryptedDataObjects();
+ PGPPrivateKey sKey = null;
+ PGPPublicKeyEncryptedData encP = null;
+ while (sKey == null && itt.hasNext()) {
+ encP = (PGPPublicKeyEncryptedData) itt.next();
+ secKey = readSecretKeyFromCol(new FileInputStream(secretFile), encP.getKeyID());
+ sKey = secKey.extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass));
+ }
+ if (sKey == null) {
+ throw new IllegalArgumentException("Secret key for message not found.");
+ }
+ InputStream clear = encP.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));
+ pgpFact = new JcaPGPObjectFactory(clear);
+ PGPCompressedData c1 = (PGPCompressedData) pgpFact.nextObject();
+ pgpFact = new JcaPGPObjectFactory(c1.getDataStream());
+ PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ InputStream inLd = ld.getDataStream();
+ int ch;
+ while ((ch = inLd.read()) >= 0) {
+ bOut.write(ch);
+ }
+ return bOut.toString();
+ }
+}
diff --git a/src/main/java/service/GpgUtil.java b/src/main/java/service/GpgUtil.java
@@ -1,145 +0,0 @@
-package service;
-
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openpgp.PGPCompressedData;
-import org.bouncycastle.openpgp.PGPEncryptedData;
-import org.bouncycastle.openpgp.PGPEncryptedDataList;
-import org.bouncycastle.openpgp.PGPException;
-import org.bouncycastle.openpgp.PGPLiteralData;
-import org.bouncycastle.openpgp.PGPObjectFactory;
-import org.bouncycastle.openpgp.PGPPrivateKey;
-import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
-import org.bouncycastle.openpgp.PGPSecretKey;
-import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
-import org.bouncycastle.openpgp.PGPUtil;
-import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
-import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
-import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
-import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
-import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Console;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.Security;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.Scanner;
-import java.util.stream.Collectors;
-
-public class GpgUtil {
-
- private static String dirPath;
- private static String secretFile;
- private static final String GPG_EXTENSION = ".gpg";
-
- public GpgUtil() {
- try {
- Properties properties = loadProperties();
- dirPath = properties.getProperty("dir.path");
- secretFile = properties.getProperty("secret.file");
- if (dirPath == null | secretFile == null)
- throw new RuntimeException("Properties missing.");
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- public Optional<String> decrypt(String fileArgument) {
- final Scanner scanner = new Scanner(System.in);
- File file;
- if (fileArgument != null) {
- file = new File(dirPath + fileArgument + GPG_EXTENSION).getAbsoluteFile();
- if (!file.exists()) throw new RuntimeException(String.format("File \"%s\" not found", file.getName()));
- } else {
- File[] files = new File(dirPath).listFiles();
- if (files == null || files.length < 1) throw new RuntimeException(dirPath + " contains no files");
- System.out.println("Which TOTP?");
- String fileNames = Arrays.stream(files)
- .filter(f -> f.getName().contains(GPG_EXTENSION))
- .map(f -> f.getName().replace(GPG_EXTENSION, ""))
- .collect(Collectors.joining(", "));
- System.out.println(fileNames);
- String fileName = scanner.nextLine();
- file = Arrays.stream(files).filter(f -> f.getName().replace(GPG_EXTENSION, "").equals(fileName)).findAny()
- .orElseThrow(() -> new RuntimeException("File not found"));
- }
-
- System.out.println("Type in GPG password.");
- Console cons = System.console();
- String pwd;
- if (cons != null) {
- pwd = new String(cons.readPassword());
- } else {
- System.out.println("Careful, input is not hidden");
- pwd = scanner.nextLine();
- }
- try {
- return Optional.ofNullable(decryptFile(new FileInputStream(file.getAbsolutePath()), pwd.toCharArray()));
- } catch (IOException | PGPException e) {
- e.printStackTrace();
- return Optional.empty();
- }
- }
-
- private Properties loadProperties() throws IOException {
- final Properties properties = new Properties();
- InputStream is = getClass().getResourceAsStream("/application.properties");
- properties.load(is);
- return properties;
- }
-
- private PGPSecretKey readSecretKeyFromCol(InputStream in, long keyId) throws IOException, PGPException {
- in = PGPUtil.getDecoderStream(in);
- PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(in, new BcKeyFingerprintCalculator());
- PGPSecretKey key = pgpSec.getSecretKey(keyId);
- if (key == null) {
- throw new IllegalArgumentException("Can't find encryption key in key ring.");
- }
- return key;
- }
-
- private String decryptFile(InputStream in, char[] pass) throws IOException, PGPException {
- Security.addProvider(new BouncyCastleProvider());
- PGPSecretKey secKey;
- in = PGPUtil.getDecoderStream(in);
- JcaPGPObjectFactory pgpFact;
-
- PGPObjectFactory pgpF = new PGPObjectFactory(in, new BcKeyFingerprintCalculator());
- Object o = pgpF.nextObject();
- PGPEncryptedDataList encList;
- if (o instanceof PGPEncryptedDataList) {
- encList = (PGPEncryptedDataList) o;
- } else {
- encList = (PGPEncryptedDataList) pgpF.nextObject();
- }
- Iterator<PGPEncryptedData> itt = encList.getEncryptedDataObjects();
- PGPPrivateKey sKey = null;
- PGPPublicKeyEncryptedData encP = null;
- while (sKey == null && itt.hasNext()) {
- encP = (PGPPublicKeyEncryptedData) itt.next();
- secKey = readSecretKeyFromCol(new FileInputStream(secretFile), encP.getKeyID());
- sKey = secKey.extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass));
- }
- if (sKey == null) {
- throw new IllegalArgumentException("Secret key for message not found.");
- }
- InputStream clear = encP.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));
- pgpFact = new JcaPGPObjectFactory(clear);
- PGPCompressedData c1 = (PGPCompressedData) pgpFact.nextObject();
- pgpFact = new JcaPGPObjectFactory(c1.getDataStream());
- PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- InputStream inLd = ld.getDataStream();
- int ch;
- while ((ch = inLd.read()) >= 0) {
- bOut.write(ch);
- }
- return bOut.toString();
- }
-}