### 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.