feat: cache password
This commit is contained in:
@@ -2,6 +2,7 @@ package me.hatter.integrations.card;
|
|||||||
|
|
||||||
public class CardHmacDecryptResult {
|
public class CardHmacDecryptResult {
|
||||||
private String plaintext;
|
private String plaintext;
|
||||||
|
private String password;
|
||||||
|
|
||||||
public String getPlaintext() {
|
public String getPlaintext() {
|
||||||
return plaintext;
|
return plaintext;
|
||||||
@@ -10,4 +11,12 @@ public class CardHmacDecryptResult {
|
|||||||
public void setPlaintext(String plaintext) {
|
public void setPlaintext(String plaintext) {
|
||||||
this.plaintext = plaintext;
|
this.plaintext = plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,6 +27,8 @@ public class Utils {
|
|||||||
private static final File CARD_CONFIG_FILE2 = new File(USER_HOME, ".config/cryptomator/card_config.json");
|
private static final File CARD_CONFIG_FILE2 = new File(USER_HOME, ".config/cryptomator/card_config.json");
|
||||||
private static final File DEFAULT_ENCRYPTION_KEY_BASE_PATH = new File(USER_HOME, ".config/cryptomator/card_keys/");
|
private static final File DEFAULT_ENCRYPTION_KEY_BASE_PATH = new File(USER_HOME, ".config/cryptomator/card_keys/");
|
||||||
|
|
||||||
|
private static final ConcurrentMap<String, String> PASSWORD_CACHE_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static boolean isCheckPassphraseStored() {
|
public static boolean isCheckPassphraseStored() {
|
||||||
final StackTraceElement stack = getCallerStackTrace();
|
final StackTraceElement stack = getCallerStackTrace();
|
||||||
if (stack != null) {
|
if (stack != null) {
|
||||||
@@ -97,12 +101,12 @@ public class Utils {
|
|||||||
throw new KeychainAccessException("Password key file: " + keyFile + " not found");
|
throw new KeychainAccessException("Password key file: " + keyFile + " not found");
|
||||||
}
|
}
|
||||||
final String encryptedKey = readFile(keyFile);
|
final String encryptedKey = readFile(keyFile);
|
||||||
final byte[] password = decrypt(cardConfig, encryptedKey);
|
final byte[] password = decrypt(cardConfig, vault, encryptedKey);
|
||||||
return new String(password, StandardCharsets.UTF_8);
|
return new String(password, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void storePassword(CardConfig cardConfig, String vault, String name, CharSequence password) throws KeychainAccessException {
|
public static void storePassword(CardConfig cardConfig, String vault, String name, CharSequence password) throws KeychainAccessException {
|
||||||
final String encryptedPassword = encrypt(cardConfig, password.toString().getBytes(StandardCharsets.UTF_8), name);
|
final String encryptedPassword = encrypt(cardConfig, vault, password.toString().getBytes(StandardCharsets.UTF_8), name);
|
||||||
final File keyFile = getKeyFile(cardConfig, vault);
|
final File keyFile = getKeyFile(cardConfig, vault);
|
||||||
writeFile(keyFile, encryptedPassword);
|
writeFile(keyFile, encryptedPassword);
|
||||||
}
|
}
|
||||||
@@ -149,32 +153,58 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] decrypt(CardConfig cardConfig, String input) throws KeychainAccessException {
|
private static byte[] decrypt(CardConfig cardConfig, String vault, String input) throws KeychainAccessException {
|
||||||
|
final List<String> params = new ArrayList<>();
|
||||||
|
params.add("hmac-decrypt");
|
||||||
|
params.add("--ciphertext");
|
||||||
|
params.add(input);
|
||||||
|
params.add("--auto-pbe");
|
||||||
|
params.add("--json");
|
||||||
|
|
||||||
|
final String password = PASSWORD_CACHE_MAP.get(vault);
|
||||||
|
if (password != null) {
|
||||||
|
params.add("--password");
|
||||||
|
params.add(password);
|
||||||
|
} else {
|
||||||
|
params.add("--outputs-password");
|
||||||
|
}
|
||||||
|
|
||||||
final UtilsCommandResult decryptResult = runCardCli(
|
final UtilsCommandResult decryptResult = runCardCli(
|
||||||
cardConfig,
|
cardConfig,
|
||||||
null,
|
null,
|
||||||
"hmac-decrypt",
|
params.toArray(new String[0])
|
||||||
"--ciphertext", input,
|
|
||||||
"--auto-pbe",
|
|
||||||
"--json"
|
|
||||||
);
|
);
|
||||||
if (decryptResult.getExitValue() != 0) {
|
if (decryptResult.getExitValue() != 0) {
|
||||||
throw new KeychainAccessException("card-cli decrypt failed: " + decryptResult);
|
throw new KeychainAccessException("card-cli decrypt failed: " + decryptResult);
|
||||||
}
|
}
|
||||||
final String resultString = new String(decryptResult.getStdout(), StandardCharsets.UTF_8);
|
final String resultString = new String(decryptResult.getStdout(), StandardCharsets.UTF_8);
|
||||||
final CardHmacDecryptResult result = new Gson().fromJson(resultString, CardHmacDecryptResult.class);
|
final CardHmacDecryptResult result = new Gson().fromJson(resultString, CardHmacDecryptResult.class);
|
||||||
|
if (result.getPassword() != null) {
|
||||||
|
PASSWORD_CACHE_MAP.put(vault, result.getPassword());
|
||||||
|
}
|
||||||
return Base64.getDecoder().decode(result.getPlaintext());
|
return Base64.getDecoder().decode(result.getPlaintext());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String encrypt(CardConfig cardConfig, byte[] input, String name) throws KeychainAccessException {
|
private static String encrypt(CardConfig cardConfig, String vault, byte[] input, String name) throws KeychainAccessException {
|
||||||
|
final List<String> params = new ArrayList<>();
|
||||||
|
params.add("hmac-encrypt");
|
||||||
|
params.add("--plaintext");
|
||||||
|
params.add(Base64.getEncoder().encodeToString(input));
|
||||||
|
params.add("--with-pbe-encrypt");
|
||||||
|
params.add("--pbe-iteration");
|
||||||
|
params.add("1000000");
|
||||||
|
params.add("--json");
|
||||||
|
|
||||||
|
final String password = PASSWORD_CACHE_MAP.get(vault);
|
||||||
|
if (password != null) {
|
||||||
|
params.add("--password");
|
||||||
|
params.add(password);
|
||||||
|
}
|
||||||
|
|
||||||
final UtilsCommandResult encryptResult = runCardCli(
|
final UtilsCommandResult encryptResult = runCardCli(
|
||||||
cardConfig,
|
cardConfig,
|
||||||
null,
|
null,
|
||||||
"hmac-encrypt",
|
params.toArray(new String[0])
|
||||||
"--plaintext", Base64.getEncoder().encodeToString(input),
|
|
||||||
"--with-pbe-encrypt",
|
|
||||||
"--pbe-iteration", "1000000",
|
|
||||||
"--json"
|
|
||||||
);
|
);
|
||||||
if (encryptResult.getExitValue() != 0) {
|
if (encryptResult.getExitValue() != 0) {
|
||||||
throw new KeychainAccessException("card-cli encrypt failed: " + encryptResult);
|
throw new KeychainAccessException("card-cli encrypt failed: " + encryptResult);
|
||||||
|
|||||||
Reference in New Issue
Block a user