mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-08-22 01:06:34 +00:00
Small fixes
This commit is contained in:
@@ -50,12 +50,13 @@ public abstract class QueryConverter<T> {
|
||||
public static final QueryConverter<SecretValue> SECRET = new QueryConverter<SecretValue>() {
|
||||
@Override
|
||||
protected SecretValue fromString(String s) {
|
||||
return new SecretValue(s);
|
||||
//TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toString(SecretValue value) {
|
||||
return value.getEncryptedValue();
|
||||
return value.getSecretValue();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package io.xpipe.core.util;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
@SuperBuilder
|
||||
@Jacksonized
|
||||
public class AesSecretValue extends EncryptedSecretValue {
|
||||
|
||||
private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
|
||||
private static final int TAG_LENGTH_BIT = 128;
|
||||
private static final int IV_LENGTH_BYTE = 12;
|
||||
private static final int AES_KEY_BIT = 128;
|
||||
private static final byte[] IV = getFixedNonce(IV_LENGTH_BYTE);
|
||||
|
||||
public AesSecretValue(char[] secret) {
|
||||
super(secret);
|
||||
}
|
||||
|
||||
private static byte[] getFixedNonce(int numBytes) {
|
||||
byte[] nonce = new byte[numBytes];
|
||||
new SecureRandom(new byte[] {1, -28, 123}).nextBytes(nonce);
|
||||
return nonce;
|
||||
}
|
||||
|
||||
protected SecretKey getAESKey(int keysize) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public byte[] encrypt(byte[] c) {
|
||||
SecretKey secretKey = getAESKey(AES_KEY_BIT);
|
||||
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LENGTH_BIT, IV));
|
||||
var bytes = cipher.doFinal(c);
|
||||
bytes = ByteBuffer.allocate(IV.length + bytes.length)
|
||||
.order(ByteOrder.LITTLE_ENDIAN)
|
||||
.put(IV)
|
||||
.put(bytes)
|
||||
.array();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public byte[] decrypt(byte[] c) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(c).order(ByteOrder.LITTLE_ENDIAN);
|
||||
byte[] iv = new byte[IV_LENGTH_BYTE];
|
||||
bb.get(iv);
|
||||
byte[] cipherText = new byte[bb.remaining()];
|
||||
bb.get(cipherText);
|
||||
|
||||
SecretKey secretKey = getAESKey(AES_KEY_BIT);
|
||||
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
|
||||
return cipher.doFinal(cipherText);
|
||||
}
|
||||
}
|
||||
@@ -67,9 +67,6 @@ public class CoreJacksonModule extends SimpleModule {
|
||||
addSerializer(Path.class, new LocalPathSerializer());
|
||||
addDeserializer(Path.class, new LocalPathDeserializer());
|
||||
|
||||
addSerializer(SecretValue.class, new SecretSerializer());
|
||||
addDeserializer(SecretValue.class, new SecretDeserializer());
|
||||
|
||||
addSerializer(DataSourceReference.class, new DataSourceReferenceSerializer());
|
||||
addDeserializer(DataSourceReference.class, new DataSourceReferenceDeserializer());
|
||||
|
||||
@@ -179,22 +176,6 @@ public class CoreJacksonModule extends SimpleModule {
|
||||
}
|
||||
}
|
||||
|
||||
public static class SecretSerializer extends JsonSerializer<SecretValue> {
|
||||
|
||||
@Override
|
||||
public void serialize(SecretValue value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
|
||||
jgen.writeString(value.getEncryptedValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static class SecretDeserializer extends JsonDeserializer<SecretValue> {
|
||||
|
||||
@Override
|
||||
public SecretValue deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
return new SecretValue(p.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@JsonSerialize(as = Throwable.class)
|
||||
public abstract static class ThrowableTypeMixIn {
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package io.xpipe.core.util;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
@SuperBuilder
|
||||
@Jacksonized
|
||||
public class EncryptedSecretValue implements SecretValue {
|
||||
|
||||
@Getter
|
||||
String encryptedValue;
|
||||
|
||||
public EncryptedSecretValue(char[] c) {
|
||||
var utf8 = StandardCharsets.UTF_8.encode(CharBuffer.wrap(c));
|
||||
var bytes = new byte[utf8.limit()];
|
||||
utf8.get(bytes);
|
||||
encryptedValue = SecretValue.base64e(encrypt(bytes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<encrypted secret>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getSecret() {
|
||||
try {
|
||||
var bytes = Base64.getDecoder().decode(encryptedValue.replace("-", "/"));
|
||||
bytes = decrypt(bytes);
|
||||
var charBuffer = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes));
|
||||
var chars = new char[charBuffer.limit()];
|
||||
charBuffer.get(chars);
|
||||
return chars;
|
||||
} catch (Exception ex) {
|
||||
return new char[0];
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -1,81 +1,28 @@
|
||||
package io.xpipe.core.util;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@AllArgsConstructor(access = AccessLevel.PUBLIC)
|
||||
@EqualsAndHashCode
|
||||
public class SecretValue {
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
public interface SecretValue {
|
||||
|
||||
String value;
|
||||
|
||||
public static SecretValue encrypt(char[] c) {
|
||||
if (c == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var utf8 = StandardCharsets.UTF_8.encode(CharBuffer.wrap(c));
|
||||
var bytes = new byte[utf8.limit()];
|
||||
utf8.get(bytes);
|
||||
Arrays.fill(c, (char) 0);
|
||||
bytes = SecretProvider.get().encrypt(bytes);
|
||||
var base64 = Base64.getEncoder().encodeToString(bytes);
|
||||
return new SecretValue(base64.replace("/", "-"));
|
||||
public static String base64e(byte[] b) {
|
||||
var base64 = Base64.getEncoder().encodeToString(b);
|
||||
return base64.replace("/", "-");
|
||||
}
|
||||
|
||||
public static SecretValue encrypt(String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return encrypt(s.toCharArray());
|
||||
}
|
||||
|
||||
public void withSecretValue(Consumer<char[]> con) {
|
||||
var chars = decryptChars();
|
||||
public default void withSecretValue(Consumer<char[]> con) {
|
||||
var chars = getSecret();
|
||||
con.accept(chars);
|
||||
Arrays.fill(chars, (char) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<secret>";
|
||||
}
|
||||
public abstract char[] getSecret();
|
||||
|
||||
public String getEncryptedValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public char[] decryptChars() {
|
||||
try {
|
||||
var bytes = Base64.getDecoder().decode(value.replace("-", "/"));
|
||||
bytes = SecretProvider.get().decrypt(bytes);
|
||||
var charBuffer = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes));
|
||||
var chars = new char[charBuffer.limit()];
|
||||
charBuffer.get(chars);
|
||||
return chars;
|
||||
} catch (Exception ex) {
|
||||
return new char[0];
|
||||
}
|
||||
}
|
||||
|
||||
public String decrypt() {
|
||||
return new String(decryptChars());
|
||||
}
|
||||
|
||||
public static SecretValue ofSecret(String s) {
|
||||
return new SecretValue(s);
|
||||
}
|
||||
|
||||
public String getSecretValue() {
|
||||
return decrypt();
|
||||
public default String getSecretValue() {
|
||||
return new String(getSecret());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user