Skip to content

Commit

Permalink
Merge branch 'security-bouncy-castle'
Browse files Browse the repository at this point in the history
  • Loading branch information
akardapolov committed Dec 27, 2022
2 parents c657a3b + a7c8031 commit ae92dbf
Show file tree
Hide file tree
Showing 27 changed files with 726 additions and 851 deletions.
35 changes: 29 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Supported databases: Oracle, PostgreSQL

- [Quick start](#quick-start)
- [How it works](#how-it-works)
- [Build](#build)
- [Security](#security)
- [Bugs and feature requests](#bugs-and-feature-requests)
- [Downloads](#downloads)
Expand All @@ -24,7 +25,7 @@ Supported databases: Oracle, PostgreSQL
- Open connection dialog and populate them with data (URL for Oracle database: **jdbc:oracle:thin:@host:port:SID**)

![ASHViewerConnectionDialog](media/connection.png)
- Press Connect button and start to monitor your system
- Press Connect button and start to monitor your system and highlight a range to show details.

![ASHViewerTop](media/top.png)
- Review Raw data interface to gain a deep insight into active session history
Expand All @@ -51,11 +52,31 @@ ASH Viewer provides graphical Top Activity, similar Top Activity analysis and Dr
For Oracle standard edition and PostgreSQL, ASH Viewer emulate ASH, storing active session data on local storage.

** Please note that v$active_session_history is a part of the Oracle Diagnostic Pack and requires a purchase of the ODP license.**

## Security
Passwords are stored in configuration file in encrypted form with secret key (computer name or hostname). So, when you run copied configuration on another host, you need to change password with a new secret key.
This is a minimal foolproof and for maximum protection it is necessary to store sensitive data using filesystem-level encryption or another way.


## Build

```shell
mvn clean package -DskipTests=true
```

## Security
Encryption and Container settings provide security for database passwords (go to Other tab -> Security block)

### Encryption
Encryption setting has AES and PBE options
- **AES** - Advanced Encryption Standard (AES) with 256-bit key encryption, from the [Bouncy Castle provider](https://www.bouncycastle.org/), [FIPS](https://www.nist.gov/standardsgov/compliance-faqs-federal-information-processing-standards-fips#:~:text=are%20FIPS%20developed%3F-,What%20are%20Federal%20Information%20Processing%20Standards%20(FIPS)%3F,by%20the%20Secretary%20of%20Commerce.) compliant algorithm;
- **PBE** - Password based encryption (PBE) in PBEWithMD5AndDES mode with secret key (computer name or hostname). This option is weak and deprecated, please use AES when possible;

### Container
It's the way to store your encrypted data
- **DBAPI** - You sensitive data stored in Windows Data Protection API (DPAPI), maximum protected, Windows only;
- **Registry** - OS System registry storage using java preferences API - weak, but better than **Configuration**;
- **Configuration** - All data in local configuration file - weak, not recommended;

### Recommendations
- use AES encryption and Windows Data Protection API (DPAPI) whenever possible;
- do not use PBE copied configuration on another host, you need to change password with a new secret key (always do it for password leak prevention).

## Bugs and feature requests
Have a bug or a feature request? [Please open an issue](https://github.com/akardapolov/ASH-Viewer/issues)

Expand All @@ -70,6 +91,8 @@ Have a bug or a feature request? [Please open an issue](https://github.com/akard
- [Berkeley DB Java Edition](http://www.oracle.com/database/berkeley-db)
- [SwingLabs GUI toolkit by alexfromsun, kleopatra, rbair and other](https://en.wikipedia.org/wiki/SwingLabs)
- [Dagger 2 by Google](https://dagger.dev/)
- [AES cipher by Bouncy Castle](https://www.bouncycastle.org/)
- [Windows DPAPI Wrapper by @peter-gergely-horvath](https://github.com/peter-gergely-horvath/windpapi4j)

## License
[![GPLv3 license](https://img.shields.io/badge/License-GPLv3-blue.svg)](http://perso.crans.org/besson/LICENSE.html)
Expand Down
4 changes: 2 additions & 2 deletions ashv/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<source>11</source>
<target>11</target>
</configuration>
</plugin>

Expand Down
7 changes: 7 additions & 0 deletions ashv/src/main/java/config/profile/ConfigProfile.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config.profile;

import core.manager.ConstantManager;
import gui.model.ContainerType;
import gui.model.EncryptionType;
import lombok.Data;

import java.util.List;
Expand All @@ -15,6 +17,11 @@ public class ConfigProfile {
private int rawRetainDays = ConstantManager.RETAIN_DAYS_MAX;
private int olapRetainDays = ConstantManager.RETAIN_DAYS_MAX;

private EncryptionType encryptionType;
private ContainerType containerType;
private String key;
private String iv;

private ConnProfile connProfile;
private List<SqlColProfile> sqlColProfileList;
}
81 changes: 81 additions & 0 deletions ashv/src/main/java/config/security/BCFipsConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package config.security;

import java.security.GeneralSecurityException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider;

/**
* This file contains API for key generation, encrypting and
* decrypting in CFB (Cipher Feedback) mode. It is similar to CBC while
* using a streaming block mode. However, padding is no longer required
* as the cipher generates a stream of "noise" which is XOR'd with the data
* to be encrypted.
*
* <a href="Based on source code from Indra Basak examples">https://github.com/indrabasak/bouncycastle-fips-examples</a>
*
* @author Indra Basak
* @since 11/18/2017
*/

@Slf4j
@Singleton
public class BCFipsConfig {

@Inject
public BCFipsConfig() {}

static {
Security.addProvider(new BouncyCastleFipsProvider());
}

/**
* Generates an AES key by providing a key size in bits.
*
* @return a symmetric key
* @throws GeneralSecurityException
*/
public SecretKey generateKey() throws GeneralSecurityException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES", "BCFIPS");
keyGenerator.init(256);
return keyGenerator.generateKey();
}

/**
* Encrypts data in CFB (Cipher Feedback) mode.
*
* @param secretKey the secret key used for encryption
* @param data the plaintext to be encrypted
* @return array with initialization vector(IV) and encrypted data
* @throws GeneralSecurityException*
*/
public byte[][] cfbEncrypt(SecretKey secretKey, byte[] data)
throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding", "BCFIPS");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return new byte[][]{cipher.getIV(), cipher.doFinal(data)};
}

/**
* Decrypts the data in CFB (Cipher Feedback) mode.
*
* @param secretKey the secret key used for decryption
* @param iv initialization vector (IV)
* @param cipherText an encrypted ciphertext
* @return array with decrypted data
* @throws GeneralSecurityException
*/
public byte[] cfbDecrypt(SecretKey secretKey, byte[] iv,
byte[] cipherText) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding", "BCFIPS");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
return cipher.doFinal(cipherText);
}

}
52 changes: 52 additions & 0 deletions ashv/src/main/java/config/security/ContainerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package config.security;

import gui.model.RegistryKey;
import java.util.Base64;
import java.util.prefs.Preferences;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Singleton
public class ContainerConfig {
private final Preferences projectPreferences;
@Inject
public ContainerConfig() {
Preferences prefsRoot = Preferences.userRoot();
projectPreferences = prefsRoot.node("ASH-Viewer");
}

public String getRegistryValue(String profileName, RegistryKey registryKey) {
return projectPreferences.get(getKey(profileName, registryKey), "");
}

public void setRegistryValue(String profileName, RegistryKey registryKey, String value) {
projectPreferences.put(getKey(profileName, registryKey), value);
}

private String getKey(String profileName, RegistryKey registryKey) {
return profileName + "_" + registryKey;
}

public String convertSecretKeyToString(SecretKey secretKey) {
byte[] rawData = secretKey.getEncoded();
return Base64.getEncoder().encodeToString(rawData);
}

public SecretKey convertStringToSecretKey(String encodedKey) {
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
}

public String convertByteToString(byte[] rawData) {
return Base64.getEncoder().encodeToString(rawData);
}

public byte[] convertStringToByte(String encodedKey) {
return Base64.getDecoder().decode(encodedKey);
}

}
Loading

0 comments on commit ae92dbf

Please sign in to comment.