mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-26 06:12:06 +01:00
Update README
This commit is contained in:
parent
b1deb75969
commit
21f2a732ee
1 changed files with 116 additions and 109 deletions
225
README.md
225
README.md
|
@ -1,22 +1,130 @@
|
|||
PGPainless - Use OpenPGP Painlessly!
|
||||
====================================
|
||||
# PGPainless - Use OpenPGP Painlessly!
|
||||
|
||||
[![Travis (.com)](https://travis-ci.com/pgpainless/pgpainless.svg?branch=master)](https://travis-ci.com/pgpainless/pgpainless)
|
||||
[![Git Tag](https://badgen.now.sh/github/tag/pgpainless/pgpainless)](https://github.com/pgpainless/pgpainless/tags)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/pgpainless/pgpainless/badge.svg?branch=master)](https://coveralls.io/github/pgpainless/pgpainless?branch=master)
|
||||
[![JavaDoc](https://badgen.net/badge/javadoc/yes/green)](https://pgpainless.org/releases/latest/javadoc/)
|
||||
[![Interoperability Test-Suite](https://badgen.net/badge/interoperable/yes/green)](https://tests.sequoia-pgp.org/)
|
||||
[![Interoperability Test-Suite](https://badgen.net/badge/Sequoia%20Test%20Suite/%232/green)](https://tests.sequoia-pgp.org/)
|
||||
|
||||
About
|
||||
-----
|
||||
## About
|
||||
|
||||
PGPainless aims to make using OpenPGP in Java projects as simple as possible.
|
||||
It does so by introducing an intuitive Builder structure, which allows easy
|
||||
setup of encryptionOptions / decrytion operations, as well as straight forward key generation.
|
||||
setup of encryptionOptions / decryption operations, as well as straight forward key generation.
|
||||
|
||||
PGPainless is based around the Bouncycastle java library and can be used on Android down to API level 10.
|
||||
It can be configured to either use the Java Cryptographic Engine (JCE), or Bouncycastles lightweight reimplementation.
|
||||
|
||||
### NOTE: PGPainless is in an early state of development. There may be dragons!
|
||||
While signature verification in Bouncycastle is limited to signature correctness, PGPainless goes much further.
|
||||
It also checks if signing subkeys are properly bound to their primary key, if keys are expired or revoked, as well as
|
||||
if keys are allowed to create signatures in the first place.
|
||||
|
||||
These rigorous checks make PGPainless stand out from other Java-based OpenPGP libraries and are the reason why
|
||||
PGPainless currently [*scores second place* on Sequoia-PGPs Interoperability Test-Suite](tests.sequoia-pgp.org).
|
||||
|
||||
## Features
|
||||
|
||||
Most of PGPainless' features can be accessed directly from the `PGPainless` class.
|
||||
If you want to get started, this class is your friend :)
|
||||
|
||||
For further details you should check out the [javadoc](https://pgpainless.org/releases/latest/javadoc/)!
|
||||
|
||||
### Easily Generate Keys
|
||||
PGPainless comes with a simple to use `KeyRingBuilder` class that helps you to quickly generate modern OpenPGP keys.
|
||||
There are some predefined key archetypes, but it is possible to fully customize key generation to your needs.
|
||||
|
||||
```java
|
||||
// RSA key without additional subkeys
|
||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
||||
.simpleRsaKeyRing("Juliet <juliet@montague.lit>", RsaLength._4096);
|
||||
|
||||
// EdDSA primary key with EdDSA signing- and XDH encryption subkeys
|
||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
||||
.modernKeyRing("Romeo <romeo@montague.lit>", "I defy you, stars!");
|
||||
|
||||
// Customized key
|
||||
PGPSecretKeyRing keyRing = PGPainless.generateKeyRing()
|
||||
.withSubKey(
|
||||
KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256))
|
||||
.withKeyFlags(KeyFlag.SIGN_DATA)
|
||||
.withDetailedConfiguration()
|
||||
.withDefaultSymmetricAlgorithms()
|
||||
.withDefaultHashAlgorithms()
|
||||
.withPreferredCompressionAlgorithms(CompressionAlgorithm.ZLIB)
|
||||
.withFeature(Feature.MODIFICATION_DETECTION)
|
||||
.done()
|
||||
).withSubKey(
|
||||
KeySpec.getBuilder(ECDH.fromCurve(EllipticCurve._P256))
|
||||
.withKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
|
||||
.withDefaultAlgorithms()
|
||||
).withMasterKey(
|
||||
KeySpec.getBuilder(RSA.withLength(RsaLength._8192))
|
||||
.withKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER)
|
||||
.withDefaultAlgorithms()
|
||||
).withPrimaryUserId("Juliet <juliet@montague.lit>")
|
||||
.withAdditionalUserId("xmpp:juliet@capulet.lit")
|
||||
.withPassphrase("romeo_oh_Romeo<3")
|
||||
.build();
|
||||
```
|
||||
|
||||
### Encrypt and Sign Data
|
||||
PGPainless makes it easy and painless to encrypt and/or sign data.
|
||||
Passed in keys are automatically evaluated, so that you don't accidentally encrypt to revoked or expired keys.
|
||||
PGPainless will furthermore detect which algorithms are supported by recipient keys and will negotiate
|
||||
algorithms accordingly.
|
||||
Still it allows you to manually specify which algorithms to use of course.
|
||||
|
||||
```java
|
||||
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
||||
.onOutputStream(outputStream)
|
||||
.withOptions(
|
||||
ProducerOptions.signAndEncrypt(
|
||||
new EncryptionOptions()
|
||||
.addRecipient(aliceKey)
|
||||
.addRecipient(bobsKey)
|
||||
// optionally encrypt to a passphrase
|
||||
.addPassphrase(Passphrase.fromPassword("password123"))
|
||||
// optionally override symmetric encryption algorithm
|
||||
.overrideEncryptionAlgorithm(SymmetricKeyAlgorithm.AES_192),
|
||||
new SigningOptions()
|
||||
// Sign in-line (using one-pass-signature packet)
|
||||
.addInlineSignature(secretKeyDecryptor, aliceSecKey, signatureType)
|
||||
// Sign using a detached signature
|
||||
.addDetachedSignature(secretKeyDecryptor, aliceSecKey, signatureType)
|
||||
// optionally override hash algorithm
|
||||
.overrideHashAlgorithm(HashAlgorithm.SHA256)
|
||||
).setAsciiArmor(true) // Ascii armor or not
|
||||
);
|
||||
|
||||
Streams.pipeAll(plaintextInputStream, encryptionStream);
|
||||
encryptionStream.close();
|
||||
```
|
||||
|
||||
### Decrypt and Verify Signatures
|
||||
|
||||
Decrypting data and verifying signatures is being done in a similar fashion.
|
||||
PGPainless will not only verify *correctness* of signatures, but also if the signing key was allowed to create the signature.
|
||||
A key might not be allowed to create signatures if, for example, it expired or was revoked, or was not properly bound to the key ring.
|
||||
Furthermore PGPainless will reject signatures made using weak algorithms like SHA-1.
|
||||
This behaviour can be modified though using the `Policy` class.
|
||||
|
||||
```java
|
||||
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
||||
.onInputStream(encryptedInputStream)
|
||||
.decryptWith(secretKeyProtector, bobSecKeys)
|
||||
.verifyWith(alicePubKeys)
|
||||
.ignoreMissingPublicKeys()
|
||||
.build();
|
||||
|
||||
Streams.pipeAll(decryptionStream, outputStream);
|
||||
decryptionStream.close();
|
||||
|
||||
// Result contains information like signature status etc.
|
||||
OpenPgpMetadata metadata = decryptionStream.getResult();
|
||||
```
|
||||
|
||||
*After* the `DecryptionStream` was closed, you can get metadata about the processed data by retrieving the `OpenPgpMetadata`.
|
||||
Again, this object will contain information about how the message was encrypted, who signed it and so on.
|
||||
|
||||
## Include PGPainless in your Project
|
||||
|
||||
|
@ -29,111 +137,10 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.pgpainless:pgpainless-core:0.1.0'
|
||||
implementation 'org.pgpainless:pgpainless-core:0.2.0-alpha12'
|
||||
}
|
||||
```
|
||||
|
||||
## How to use PGPainless
|
||||
|
||||
The entry point to the API is the `PGPainless` class. Here you can find methods for a quick start :)
|
||||
|
||||
### Generate Keys
|
||||
|
||||
The first thing you probably want to do is generate you some nice tasty Key Pairs. The most straight forward way to do so is by calling
|
||||
|
||||
```java
|
||||
PGPKeyRing keyRing = PGPainless.generateKeyRing()
|
||||
.simpleRsaKeyRing("Juliet <juliet@montague.lit>", RsaLength._4096);
|
||||
```
|
||||
|
||||
but feel free to explore the API further. PGPainless allows you to create Key Pairs consisting of a master key plus several sub keys, even with different algorithms at the same time!
|
||||
Take for example a look at this delicious key:
|
||||
|
||||
```java
|
||||
PGPSecretKeyRing keyRing = PGPainless.generateKeyRing()
|
||||
.withSubKey(
|
||||
KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256))
|
||||
.withKeyFlags(KeyFlag.SIGN_DATA)
|
||||
.withDetailedConfiguration()
|
||||
.withDefaultSymmetricAlgorithms()
|
||||
.withDefaultHashAlgorithms()
|
||||
.withPreferredCompressionAlgorithms(CompressionAlgorithm.ZLIB)
|
||||
.withFeature(Feature.MODIFICATION_DETECTION)
|
||||
.done())
|
||||
.withSubKey(
|
||||
KeySpec.getBuilder(ECDH.fromCurve(EllipticCurve._P256))
|
||||
.withKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
|
||||
.withDefaultAlgorithms())
|
||||
.withMasterKey(
|
||||
KeySpec.getBuilder(RSA.withLength(RsaLength._8192))
|
||||
.withKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER)
|
||||
.withDefaultAlgorithms())
|
||||
.withPrimaryUserId("Juliet <juliet@montague.lit>")
|
||||
.withPassphrase("romeo_oh_Romeo<3")
|
||||
.build();
|
||||
```
|
||||
|
||||
### Encrypt / Sign Data
|
||||
|
||||
Encrypting and signingOptions data is pretty straight forward as well.
|
||||
```java
|
||||
EncryptionStream encryptor = PGPainless.encryptAndOrSign()
|
||||
.onOutputStream(targetOuputStream)
|
||||
.toRecipients(publicKeyRings)
|
||||
.usingSecureAlgorithms()
|
||||
.signWith(secretKeyDecryptor, signingKeyRing)
|
||||
.noArmor();
|
||||
```
|
||||
|
||||
Note: Despite the name, the `EncryptionStream` can be used to sign only as well. Simply replace the `.toRecipients()` option with `doNotEncrypt()`.
|
||||
|
||||
The resulting `EncryptionStream` can then be used to encrypt data like follows:
|
||||
|
||||
```java
|
||||
Streams.pipeAll(sourceInputStream, encryptor);
|
||||
sourceInputStream.close();
|
||||
encryptor.close();
|
||||
```
|
||||
|
||||
The encrypted data will be written to the provided `targetOutputStream`.
|
||||
|
||||
Additionally you can get information about the encrypted data by calling
|
||||
|
||||
```java
|
||||
OpenPgpMetadata result = encryptor.getResult();
|
||||
```
|
||||
|
||||
This object will contain information like to which keys the message is encrypted, which keys were used for signingOptions and so on.
|
||||
|
||||
### Decrypt / Verify Encrypted Data
|
||||
|
||||
To process incoming encrypted / signed data, just do the following:
|
||||
|
||||
```java
|
||||
DecryptionStream decryptor = PGPainless.decryptAndOrVerify()
|
||||
.onInputStream(sourceInputStream) // insert encrypted data here
|
||||
.decryptWith(secretKeyDecryptor, secretKey)
|
||||
.verifyWith(trustedKeyIds, senderKeys)
|
||||
.ignoreMissingPublicKeys()
|
||||
.build();
|
||||
```
|
||||
|
||||
Again, the resulting `DecryptionStream` can be used like a normal stream.
|
||||
|
||||
```java
|
||||
Streams.pipeAll(decryptor, targetOutputStream);
|
||||
decryptor.close();
|
||||
```
|
||||
|
||||
*After* the `DecryptionStream` was closed, you can get metadata about the processed data by retrieving the `OpenPgpMetadata`.
|
||||
Again, this object will contain information about how the message was encrypted, who signed it and so on.
|
||||
|
||||
```java
|
||||
OpenPgpMetadata result = decryptor.getResult();
|
||||
```
|
||||
|
||||
For further details you should check out the [javadoc](https://pgpainless.org/releases/latest/javadoc/)!
|
||||
|
||||
## About
|
||||
PGPainless is a by-product of my [Summer of Code 2018 project](https://blog.jabberhead.tk/summer-of-code-2018/).
|
||||
For that project I was in need of a simple to use OpenPGP library.
|
||||
|
|
Loading…
Reference in a new issue