[](https://github.com/BottleFmt/bottlerl/actions/workflows/ci.yml)
[](https://hex.pm/packages/bottlerl)
[](https://hexdocs.pm/bottlerl)
# bottlerl
An Erlang/OTP library for the Bottle Protocol, providing layered message containers with encryption and signatures. Compatible with the [Go reference implementation](https://github.com/BottleFmt/gobottle).
## Installation
Add to your `rebar.config` dependencies:
```erlang
{deps, [
{bottlerl, "0.1.1"}
]}.
```
Or from git:
```erlang
{deps, [
{bottlerl, {git, "https://github.com/BottleFmt/bottlerl.git", {tag, "0.1.1"}}}
]}.
```
Requires Erlang/OTP 28 or later.
## Features
- **Bottle**: Layered message containers with encryption and signatures
- **ECDH Encryption**: Message encryption using ECDSA/ECDH and Ed25519/X25519 keys
- **Digital Signatures**: Support for RSA, ECDSA (P-256), and Ed25519
- **IDCard**: Identity management with sub-keys and key purposes
- **Keychain**: Key storage and management
- **Serialization**: CBOR (RFC 8949) and JSON encoding
## Quick Start
### Creating and Opening Bottles
```erlang
%% Create a bottle with a message
Bottle = bottlerl:new(<<"secret message">>),
%% Encrypt for a recipient
{ok, EncryptedBottle} = bottlerl:encrypt(Bottle, [RecipientPublicKey]),
%% Sign the bottle
{ok, SignedBottle} = bottlerl:sign(EncryptedBottle, SenderPrivateKey),
%% Serialize to CBOR
{ok, Binary} = bottlerl:to_cbor(SignedBottle),
%% Open the bottle
Opener = bottlerl:new_opener([RecipientPrivateKey]),
{ok, Message, Result} = bottlerl:open(Opener, SignedBottle),
%% Check signatures
case bottlerl_opener:signed_by(Result#open_result.signatures, SenderPublicKey) of
true -> io:format("Verified signature from sender~n");
false -> io:format("Signature not found~n")
end.
```
### Key Generation
```erlang
%% Generate RSA key pair
RsaPrivateKey = bottlerl_crypto:generate_rsa_key(2048),
%% Generate EC key pair (P-256)
EcPrivateKey = bottlerl_crypto:generate_ec_key(secp256r1),
%% Generate Ed25519 key pair
Ed25519PrivateKey = bottlerl_crypto:generate_ed25519_key(),
%% Get public key from private key
PublicKey = bottlerl_crypto:private_key_to_public_key(PrivateKey),
%% Convert to DER format for storage/transmission
PublicKeyDer = bottlerl_crypto:public_key_to_der(PublicKey).
```
### Keychain Management
```erlang
%% Create a keychain
Keychain = bottlerl:new_keychain(),
%% Add keys
{ok, Keychain1} = bottlerl:add_key(Keychain, PrivateKey1),
{ok, Keychain2} = bottlerl:add_key(Keychain1, PrivateKey2),
%% Use keychain with opener
Opener = bottlerl:new_opener(Keychain2),
{ok, Message, _Result} = bottlerl:open(Opener, EncryptedBottle).
```
### IDCard Management
```erlang
%% Create an IDCard for a public key
{ok, IDCard} = bottlerl_idcard:new(PublicKey),
%% Add metadata
IDCard1 = bottlerl_idcard:set_meta(IDCard, <<"name">>, <<"Alice">>),
%% Add a subkey with purposes
{ok, _SubKey, IDCard2} = bottlerl_idcard:find_key(IDCard1, SubKeyDer, true),
IDCard3 = bottlerl_idcard:set_key_purposes(IDCard2, SubKeyDer, [<<"sign">>, <<"decrypt">>]),
%% Sign and serialize the IDCard
{ok, SignedIDCard} = bottlerl_idcard:sign(IDCard3, PrivateKey),
%% Load and verify an IDCard
{ok, LoadedIDCard} = bottlerl_idcard:from_binary(SignedIDCard).
```
## Modules
| Module | Description |
|--------|-------------|
| `bottlerl` | Main API facade |
| `bottlerl_bottle` | Bottle creation, encryption, and signing |
| `bottlerl_opener` | Bottle decryption and signature verification |
| `bottlerl_crypto` | Cryptographic operations |
| `bottlerl_cbor` | CBOR encoding/decoding (RFC 8949) |
| `bottlerl_json` | JSON encoding/decoding |
| `bottlerl_idcard` | Identity card management |
| `bottlerl_keychain` | Key storage and lookup |
| `bottlerl_membership` | Group membership handling |
## Supported Key Types
| Type | Signing | Encryption |
|------|---------|------------|
| ECDSA (P-256) | Yes | Yes (via ECDH) |
| Ed25519 | Yes | Yes (via X25519) |
| RSA | Yes | Yes (OAEP) |
## Interoperability
This library is fully compatible with the Go reference implementation ([gobottle](https://github.com/BottleFmt/gobottle)). Messages encrypted or signed by one implementation can be decrypted and verified by the other.
The test suite includes interoperability tests using test vectors generated by the Go implementation.
## Running Tests
```bash
rebar3 ct
```
## License
MIT License - see [LICENSE](LICENSE) file.