mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-22 19:08:00 +01:00
Quickstart guide: Add sections on encrypting, signing, decryption, verification
This commit is contained in:
parent
bc24c4626a
commit
4efe8fb468
1 changed files with 176 additions and 3 deletions
|
@ -132,6 +132,22 @@ armorOut.close(); // important!
|
|||
|
||||
The output stream will now contain the ASCII armored representation of the binary data.
|
||||
|
||||
If the data you want to wrap in ASCII armor is non-OpenPGP data (e.g. the String "Hello World!"),
|
||||
you need to use the following code:
|
||||
|
||||
```java
|
||||
InputStream inputStream = ...;
|
||||
OutputStream output = ...;
|
||||
|
||||
EncryptionStream armorStream = PGPainless.encryptAndOrSign()
|
||||
.onOutputStream(output)
|
||||
.withOptions(ProducerOptions.noEncryptionNoSigning()
|
||||
.setAsciiArmor(true));
|
||||
|
||||
Streams.pipeAll(inputStream, armorStream);
|
||||
armorStream.close();
|
||||
```
|
||||
|
||||
To remove ASCII armor, you can make use of BouncyCastle's `ArmoredInputStream` as follows:
|
||||
|
||||
```java
|
||||
|
@ -146,10 +162,167 @@ armorIn.close();
|
|||
The output stream will now contain the binary OpenPGP data.
|
||||
|
||||
### Encrypt and/or Sign a Message
|
||||
TODO
|
||||
Encrypting and signing messages is done using the same API in PGPainless.
|
||||
The type of action depends on the configuration of the `ProducerOptions` class, which in term accepts
|
||||
`SigningOptions` and `EncryptionOptions` objects:
|
||||
|
||||
```java
|
||||
// Encrypt only
|
||||
ProducerOptions options = ProducerOptions.encrypt(encryptionOptions);
|
||||
|
||||
// Sign only
|
||||
ProducerOptions options = ProducerOptions.sign(signingOptions);
|
||||
|
||||
// Sign and encrypt
|
||||
ProducerOptions options = ProducerOptions.signAndEncrypt(signingOptions, encryptionOptions);
|
||||
```
|
||||
|
||||
The `ProducerOptions` object can then be passed into the `encryptAndOrSign()` API:
|
||||
|
||||
```java
|
||||
InputStream plaintext = ...; // The data that shall be encrypted and/or signed
|
||||
OutputStream ciphertext = ...; // Destination for the ciphertext
|
||||
|
||||
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
||||
.onOutputStream(ciphertext)
|
||||
.withOptions(options); // pass in the options object
|
||||
|
||||
Streams.pipeAll(plaintext, encryptionStream); // pipe the data through
|
||||
encryptionStream.close(); // important! Close the stream to finish encryption/signing
|
||||
|
||||
EncryptionResult result = encryptionStream.getResult(); // metadata
|
||||
```
|
||||
|
||||
The `ciphertext` output stream now contains the encrypted and/or signed data.
|
||||
|
||||
Now lets take a look at the configuration of the `SigningOptions` object and how to instruct PGPainless to add a simple
|
||||
signature to the message:
|
||||
|
||||
```java
|
||||
PGPSecretKeyRing signingKey = ...; // Key used for signing
|
||||
SecretKeyRingProtector protector = ...; // Protector to unlock the signing key
|
||||
|
||||
SigningOptions signOptions = SigningOptions.get()
|
||||
.addSignature(protector, signingKey);
|
||||
```
|
||||
This will add an inline signature to the message.
|
||||
|
||||
It is possible to add multiple signatures from different keys by repeating the `addSignature()` method call.
|
||||
|
||||
If instead of an inline signature, you want to create a detached signature instead (e.g. because you do not want
|
||||
to alter the data you are signing), you can add the signature as follows:
|
||||
|
||||
```java
|
||||
signOptions.addDetachedSignature(protector, signingKey);
|
||||
```
|
||||
|
||||
Passing in the `SigningOptions` object like this will result in the signature not being added to the message itself.
|
||||
Instead, the signature can later be acquired from the `EncryptionResult` object via `EncryptionResult.getDetachedSignatures()`.
|
||||
That way, it can be distributed independent of the message.
|
||||
|
||||
The `EncryptionOptions` object can be configured in a similar way:
|
||||
|
||||
```java
|
||||
PGPPublicKey certificate = ...;
|
||||
|
||||
EncryptionOptions encOptions = EncryptionOptions.get()
|
||||
.addRecipient(certificate);
|
||||
```
|
||||
|
||||
Once again, it is possible to add multiple recipients by repeating the `addRecipient()` method call.
|
||||
|
||||
You can also encrypt a message to a password like this:
|
||||
```java
|
||||
encOptions.addPassphrase(Passphrase.fromPassword("sw0rdf1sh"));
|
||||
```
|
||||
|
||||
Both methods can be used in combination to create a message which can be decrypted with either a recipients secret key
|
||||
or the passphrase.
|
||||
|
||||
### Decrypt and/or Verify a Message
|
||||
TODO
|
||||
Decryption and verification of a message is both done using the same API.
|
||||
Whether a message was actually signed / encrypted can be determined after the message has been processed by checking
|
||||
the `OpenPgpMetadata` object which can be obtained from the `DecryptionStream`.
|
||||
|
||||
To configure the decryption / verification process, the `ConsumerOptions` object is used:
|
||||
|
||||
```java
|
||||
PGPPublicKeyRing verificationCert = ...; // optional, signers certificate for signature verification
|
||||
PGPSecretKeyRing decryptionKey = ...; // optional, decryption key
|
||||
|
||||
ConsumerOptions options = ConsumerOptions.get()
|
||||
.addVerificationCert(verificationCert) // add a verification cert for signature verification
|
||||
.addDecryptionKey(decryptionKey); // add a secret key for message decryption
|
||||
```
|
||||
|
||||
Both verification certificates and decryption keys are optional.
|
||||
If you know the message is signed, but not encrypted you can omit providing a decryption key.
|
||||
Same goes for if you know that the message is encrypted, but not signed.
|
||||
In this case you can omit the verification certificate.
|
||||
|
||||
On the other hand, providing these parameters does not hurt.
|
||||
PGPainless will ignore unused keys / certificates, so if you provide a decryption key and the message is not encrypted,
|
||||
nothing bad will happen.
|
||||
|
||||
It is possible to provide multiple verification certs and decryption keys. PGPainless will pick suitable ones on the fly.
|
||||
If the message is signed with key `0xAAAA` and you provide certificates `0xAAAA` and `0xBBBB`, it will verify
|
||||
with cert `0xAAAA` and ignore `0xBBBB`.
|
||||
|
||||
To do the actual decryption / verification of the message, do the following:
|
||||
|
||||
```java
|
||||
InputStream ciphertext = ...; // encrypted and/or signed message
|
||||
OutputStream plaintext = ...; // destination for the plaintext
|
||||
|
||||
ConsumerOptions options = ...; // see above
|
||||
DecryptionStream consumerStream = PGPainless.decryptAndOrVerify()
|
||||
.onInputStream(ciphertext)
|
||||
.withOptions(options);
|
||||
|
||||
Streams.pipeAll(consumerStream, plaintext);
|
||||
consumerStream.close(); // important!
|
||||
|
||||
// The result will contain metadata of the message
|
||||
OpenPgpMetadata result = consumerStream.getResult();
|
||||
```
|
||||
|
||||
After the message has been processed, you can consult the `OpenPgpMetadata` object to determine the nature of the message:
|
||||
|
||||
```java
|
||||
boolean wasEncrypted = result.isEncrypted();
|
||||
SubkeyIdentifier decryptionKey = result.getDecryptionKey();
|
||||
Map<SubkeyIdentifier, PGPSignature> validSignatures = result.getVerifiedSignatures();
|
||||
boolean wasSignedByCert = result.containsVerifiedSignatureFrom(certificate);
|
||||
|
||||
// For files:
|
||||
String fileName = result.getFileName();
|
||||
Date modificationData = result.getModificationDate();
|
||||
```
|
||||
|
||||
### Verify a Signature
|
||||
TODO
|
||||
In some cases, detached signatures are distributed alongside the message.
|
||||
This is the case for example with Debians `Release` and `Release.gpg` files.
|
||||
Here, `Release` is the plaintext message, which is unaltered by the signing process while `Release.gpg` contains
|
||||
the detached OpenPGP signature.
|
||||
|
||||
To verify a detached signature, you need to call the PGPainless API like this:
|
||||
|
||||
```java
|
||||
InputStream plaintext = ...; // e.g. new FileInputStream(releaseFile);
|
||||
InputStream detachedSignature = ...; // e.g. new FileInputStream(releaseGpgFile);
|
||||
PGPPublicKeyRing certificate = ...; // e.g. debians public signing key
|
||||
|
||||
ConsumerOptions options = ConsumerOptions.get()
|
||||
.addVerificationCert(certificate) // provide certificate for verification
|
||||
.addVerificationOfDetachedSignatures(detachedSignature) // provide detached signature
|
||||
|
||||
DecryptionStream verificationStream = PGPainless.decryptAndOrVerify()
|
||||
.onInputStream(plaintext)
|
||||
.withOptions(options);
|
||||
|
||||
Streams.drain(verificationStream); // push all the data through the stream
|
||||
verificationStream.close(); // finish verification
|
||||
|
||||
OpenPgpMetadata result = verificationStream.getResult(); // get metadata of signed message
|
||||
assertTrue(result.containsVerifiedSignatureFrom(certificate)); // check if message was in fact signed
|
||||
```
|
Loading…
Reference in a new issue