Skip to content

Commit

Permalink
Add encryption, digest and secret support to security (helidon-io#2872)
Browse files Browse the repository at this point in the history
* Add encryption, digest and secret support to security
* First implementation of encryption and secrets based on config
  • Loading branch information
tomas-langer authored and aseovic committed Apr 26, 2021
1 parent d4ac68e commit 5591898
Show file tree
Hide file tree
Showing 16 changed files with 1,235 additions and 13 deletions.
2 changes: 1 addition & 1 deletion config/encryption/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2017, 2021 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020 Oracle and/or its affiliates.
* Copyright (c) 2018, 2021 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -146,18 +146,33 @@ public static String encryptRsa(PublicKey key, String secret) throws ConfigEncry
* @throws ConfigEncryptionException If any problem with encryption occurs
*/
public static String encryptAes(char[] masterPassword, String secret) throws ConfigEncryptionException {
Objects.requireNonNull(secret, "Secret message must be provided to be encrypted");

return encryptAesBytes(masterPassword, secret.getBytes(StandardCharsets.UTF_8));
}

/**
* Encrypt using AES with GCM method, key is derived from password with random salt.
*
* @param masterPassword master password
* @param secret secret to encrypt
* @return Encrypted value base64 encoded
* @throws ConfigEncryptionException If any problem with encryption occurs
* @deprecated this method will be removed once a separate module for encryption is created
*/
@Deprecated(since = "2.2.0")
public static String encryptAesBytes(char[] masterPassword, byte[] secret) throws ConfigEncryptionException {
Objects.requireNonNull(masterPassword, "Password must be provided for encryption");
Objects.requireNonNull(secret, "Secret message must be provided to be encrypted");

byte[] salt = SECURE_RANDOM.generateSeed(SALT_LENGTH);
byte[] nonce = SECURE_RANDOM.generateSeed(NONCE_LENGTH);
byte[] secretBytes = secret.getBytes(StandardCharsets.UTF_8);

Cipher cipher = cipher(masterPassword, salt, nonce, Cipher.ENCRYPT_MODE);
// encrypt
byte[] encryptedMessageBytes;
try {
encryptedMessageBytes = cipher.doFinal(secretBytes);
encryptedMessageBytes = cipher.doFinal(secret);
} catch (Exception e) {
throw new ConfigEncryptionException("Failed to encrypt", e);
}
Expand Down Expand Up @@ -250,6 +265,22 @@ public static String decryptAesLegacy(char[] masterPassword, String encryptedBas
* @throws ConfigEncryptionException if something bad happens during decryption (e.g. wrong password)
*/
public static String decryptAes(char[] masterPassword, String encryptedBase64) throws ConfigEncryptionException {
return new String(decryptAesBytes(masterPassword, encryptedBase64), StandardCharsets.UTF_8);
}

/**
* Decrypt using AES.
* Will only decrypt messages encrypted with {@link #encryptAes(char[], String)} as the algorithm used is quite custom
* (number of bytes of seed, of salt and approach).
*
* @param masterPassword master password
* @param encryptedBase64 encrypted secret, base64 encoded
* @return Decrypted secret
* @throws ConfigEncryptionException if something bad happens during decryption (e.g. wrong password)
* @deprecated This method will be moved to a new module
*/
@Deprecated(since = "2.2.0")
public static byte[] decryptAesBytes(char[] masterPassword, String encryptedBase64) {
Objects.requireNonNull(masterPassword, "Password must be provided for encryption");
Objects.requireNonNull(encryptedBase64, "Encrypted bytes must be provided for decryption (base64 encoded)");

Expand All @@ -275,10 +306,10 @@ public static String decryptAes(char[] masterPassword, String encryptedBase64) t
byte[] originalBytes = new byte[decryptedBytes.length];
System.arraycopy(decryptedBytes, 0, originalBytes, 0, originalBytes.length);

return new String(originalBytes, StandardCharsets.UTF_8);
return originalBytes;
} catch (Throwable e) {
throw new ConfigEncryptionException("Failed to decrypt value using AES. Returning clear text value as is: "
+ encryptedBase64, e);
+ encryptedBase64, e);
}
}

Expand Down
2 changes: 1 addition & 1 deletion config/encryption/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020 Oracle and/or its affiliates.
* Copyright (c) 2017, 2021 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
64 changes: 64 additions & 0 deletions security/providers/config-vault/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2021 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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>
<parent>
<groupId>io.helidon.security.providers</groupId>
<artifactId>helidon-security-providers-project</artifactId>
<version>2.3.0-SNAPSHOT</version>
</parent>
<artifactId>helidon-security-providers-config-vault</artifactId>
<name>Helidon Security Providers Config Vault</name>

<description>
An implementation of Vault like features based on configuration only.
Provide secrets, and encryption/decryption.
All secret operations are based on master password.
For full production solutions, please use OCI Vault or similar integrations.
</description>

<dependencies>
<dependency>
<groupId>io.helidon.security</groupId>
<artifactId>helidon-security</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-encryption</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.bundles</groupId>
<artifactId>helidon-bundles-config</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Loading

0 comments on commit 5591898

Please sign in to comment.