### Install Bouncy Castle Provider
Source: https://neuhalje.github.io/bouncy-gpg
Register the Bouncy Castle provider in your application code if it is not already installed.
```java
// in one of you classed install the BC provider
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
```
--------------------------------
### Derive a 256-bit key from a password with SCryptKeyStretching
Source: https://neuhalje.github.io/bouncy-gpg/howto/keys/passwords/example/convertingpasswordsintocryptographickeys
Uses SCryptKeyStretching with forStrongInputKeyMaterial() to derive a 256-bit key from a strong password. The salt must never change and should be random and roughly as long as the key. The example returns the derived key; the output is 0x89d4a9b23d8a88d09e559aeeaa7cfa4a029673b01d969a2f523a7c1f749c330b.
```java
import java.nio.charset.StandardCharsets;
import org.bouncycastle.util.encoders.Hex;
import name.neuhalfen.projects.crypto.symmetric.keygeneration.impl.stretching.KeyStretching;
import name.neuhalfen.projects.crypto.symmetric.keygeneration.impl.stretching.SCryptKeyStretching;
// the password
// Rather obviously the password should NOT be stored as part of the source code
String password = "39akldsAFQqwmsx-+#aQcsvcu82cQd,.-ask72=cq8csf";
// The salt value should be application or installation specific.
// It is an absolute MUST that the salt is never changed! A different salt WILL result in a different
// key being generated!
// The salt value SHOULD be roughly as long as the key (e.g. 128/256 bit).
// The salt value SHOULD be random (so this salt value is actually a bad example)
final byte[] SALT = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
// In this case we are using a 256 bit key, e.g. for AES-256.
final int DESIRED_KEY_LENGTH = 256;
// Use forSensitiveStorage to derive e.g. a masterkey at application startup.
// forSensitiveStorage is really slow. If you are very sure that you have a very
// good (22 characters random or longer) password for 128 bit keys / 44 character
// passwords for 256 bit keys you can consider using forQuickDerivation.
final SCryptKeyStretching.SCryptKeyStretchingParameters stretchingParameters = SCryptKeyStretching.SCryptKeyStretchingParameters.forStrongInputKeyMaterial();
final KeyStretching streching = new SCryptKeyStretching(stretchingParameters);
byte[] key = streching.strengthenKey(SALT, password.getBytes(StandardCharsets.UTF_8), DESIRED_KEY_LENGTH);
return key;
```
--------------------------------
### Derive AES-128 key and IV using DerivedKeyGenerator
Source: https://neuhalje.github.io/bouncy-gpg/howto/keys/kdf/example/derivingfromcryptographickeys
Demonstrates deriving an AES-128 key and IV for a specific database record using the DerivedKeyGeneratorFactory. The master key and salt should not be hardcoded in production environments.
```java
import java.security.GeneralSecurityException;
import name.neuhalfen.projects.crypto.symmetric.keygeneration.DerivedKeyGenerator;
import name.neuhalfen.projects.crypto.symmetric.keygeneration.DerivedKeyGeneratorFactory;
import org.bouncycastle.util.encoders.Hex;
// Rather obviously the master key MUST NOT be part of the source code!
// This is only for demonstration purposes!
byte[] masterkey = Hex.decode("81d0994d0aa21b786d6b8dc45fc09f31");
// The salt value should not be part of the source code.
// The same salt value can be reused for all key derivations.
byte[] salt = Hex.decode("b201445d3bcdc7a07c469b7d7ef8988c");
// These settings depend on the algorithms used.
// This combination could e.g. be used for AES-256 in CTR or CBC mode
final int IV_LENGTH_BYTES = 128 / 8;
// This is the length of the generated key.
// For AES-256 use KEY_LENGTH_BYTES = 256/8
final int KEY_LENGTH_BYTES = 128 / 8;
// The key to be generated depends on three things:
// - the master key
// - the salt value
// - the info
// Master key and salt are relatively static and are often scoped "per installation of the application".
//
// The info value must(!) uniquely(!) identify the object to be encrypted.
// It is mandatory that the same key/iv combination is not used multiple times.
// A good way to do this is to use a combination of the objects type, id, and version.
// Version means: "This is incremented every time the record is changed".
// Using a random value (that is refreshed for each update) is also possible.
String context = "MY_TABLE";
String databasePrimaryKey = "2386221";
String recordVersion = "3";
final DerivedKeyGenerator derivedKeyGenerator =
DerivedKeyGeneratorFactory
.fromInputKey(masterkey)
.andSalt(salt)
.withHKDFsha256();
final byte[] iv = new byte[IV_LENGTH_BYTES];
final byte[] key = new byte[KEY_LENGTH_BYTES];
// The key derivation creates (arbitrary long) streams of "randomness" (it is a PRF - pseudo random function).
// Request enough randomness to cover IV and key
final byte[] keyAndIV = derivedKeyGenerator
.deriveKey(context, databasePrimaryKey, recordVersion, IV_LENGTH_BYTES + KEY_LENGTH_BYTES);
System.arraycopy(keyAndIV, 0, key, 0, key.length);
System.arraycopy(keyAndIV, key.length, iv, 0, iv.length);
System.out.println("IV: " + Hex.toHexString(iv));
System.out.println("Key: " + Hex.toHexString(key));
IV: 3af706a49e4d9bb09cbdb01bbfc9d8ff
Key: 551cb7df244e577b5b556634117c3895
```
--------------------------------
### Add Bouncy-GPG Maven Repository and Dependency
Source: https://neuhalje.github.io/bouncy-gpg
Configure the repository and dependency in your pom.xml file.
```xml
bintray
bintray
false
http://jcenter.bintray.com
```
```xml
name.neuhalfen.projects.crypto.bouncycastle.openpgp
bouncy-gpg
2.0.1
```
--------------------------------
### Add Bouncy-GPG Gradle Dependency
Source: https://neuhalje.github.io/bouncy-gpg
Add the Bouncy Castle and Bouncy-GPG dependencies to your build.gradle file.
```gradle
// build.gradle
// in build.gradle add a dependency to bouncy castle and bouncy-gpg
//...
repositories {
mavenCentral()
jcenter()
}
//...
// ...
dependencies {
compile 'org.bouncycastle:bcprov-jdk15on:1.57'
compile 'org.bouncycastle:bcpg-jdk15on:1.57'
// ...
compile 'name.neuhalfen.projects.crypto.bouncycastle.openpgp:bouncy-gpg:2.+'
// ...
}
```
--------------------------------
### Decrypting a file and validating the signature
Source: https://neuhalje.github.io/bouncy-gpg
Decrypts an encrypted GPG file and verifies the signature using the provided keyring configuration.
```java
final KeyringConfig keyringConfig = KeyringConfigs
.withKeyRingsFromFiles(
"pubring.gpg",
"secring.gpg",
KeyringConfigCallbacks.withPassword("s3cr3t"));
try (
final FileInputStream cipherTextStream = new FileInputStream("/tmp/encrypted.gpg");
final FileOutputStream fileOutput = new FileOutputStream(destFile);
final BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutput);
final InputStream plaintextStream = BouncyGPG
.decryptAndVerifyStream()
.withConfig(keyringConfig)
.andIgnoreSignatures()
.fromEncryptedInputStream(cipherTextStream)
) {
Streams.pipeAll(plaintextStream, bufferedOut);
}
```
--------------------------------
### Encrypting a file with Bouncy GPG
Source: https://neuhalje.github.io/bouncy-gpg
Encrypts /tmp/plaintext.txt for a recipient and signs it with a sender's key, writing the result to /tmp/encrypted.gpg.
```java
final KeyringConfig keyringConfig = KeyringConfigs
.withKeyRingsFromFiles(
"pubring.gpg",
"secring.gpg",
KeyringConfigCallbacks.withPassword("s3cr3t"));
try (
final FileOutputStream fileOutput = new FileOutputStream("/tmp/encrypted.gpg");
final BufferedOutputStream bufferedOut = new BufferedOutputStream(fileOutput);
final OutputStream outputStream = BouncyGPG
.encryptToStream()
.withConfig(keyringConfig)
.withStrongAlgorithms()
.toRecipient("recipient@example.com")
.andSignWith("sender@example.com")
.binaryOutput()
.andWriteTo(bufferedOut);
final FileInputStream is = new FileInputStream("/tmp/plaintext.txt")
) {
Streams.pipeAll(is, outputStream);
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.