e-Wallets APIs support either PGP or JWE for application layer encryption.

## PGP encryption

PGP is a standard set of encryption, decryption, and signing algorithms which
provide cryptographic privacy and authentication.

When using PGP to encrypt payloads, partners must support:

- Encrypting and decrypting payloads with multiple PGP keys.
- Signing payloads with multiple PGP keys.
- Verifying a payload with multiple signatures, any one of which can be the signature with the key provided by Google.
- Decryption of Web-safe base64 encoded payloads.

PGP public keys provided to Google must have a subkey used for encryption. The
subkey allows for independent rotation from the primary key. The primary key is
used for identity verification. Private keys must be 2048 (or greater) bit RSA
keys that **expire in one year** with a **maximum lifetime of two years**.

Before beginning development you need to exchange PGP keys with Google.
In this step, you generate a PGP public-private key pair, provide the public
key to Google, and receive a public key back from Google. During development,
you will only need to exchange sandbox keys used for development and testing
outside of production. Before production testing and launch, you will need to
perform another exchange of production keys.

### Generating a new PGP key

Assuming you have a [GPG binary](https://gnupg.org/) in your system path, you
can use the following POSIX command to create a new key pair.

    $ gpg --full-generate-key

When prompted, select an RSA key with at least 2048 bits of entropy and an
expiration of 1-2 years. This command should create both a primary key
*(labeled SC, for 'S'igning and 'C'ertificate generation)* and a subkey
*(labeled E, for 'E'ncryption)*.

### Key Rotation

To ensure uninterrupted service during key rotations, the system supports
multiple active PGP keys for both partners and Google.

- You can sign payloads with both old and new keys during their rotation.
  Google will validate the signature against
  any active public key Google has on file.

- When you need to rotate your Google public keys, you can encrypt payloads to
  both old and new Google public keys. Google can decrypt with either key.

- PGP key IDs within the message itself enable automatic key identification,
  eliminating the need for payload version fields or coordinated switchover
  times.

## PGP Library Configuration

### Sending Payloads

1. When signing, you should use `SHA384` as the digest algorithm; don't use `SHA1`or `MD5`
2. When encrypting, you should use `AES256` as the symmetric encryption algorithm; don't use `CAST5` or `IDEA`
3. When encrypting or signing messages, be sure to select the sub key with the corresponding purpose; use the `CAN_SIGN` key for signing and the `ENCRYPT_COMMS`/`ENCRYPT_STORAGE` key for encrypting

### Receiving Payloads

1. When verifying a payload, make sure your library supports modern hash algorithms like `SHA384`. Google will begin using it on all new keys as of May 14, 2023.
2. When decrypting a payload, make sure your library supports modern symmetric encryption algorithms like `AES256`. Google will begin using it on all new keys as of May 14, 2023.

### GPG Payload Encryption Example

The following command is an example of how to select secure options when using
GPG. It is expected that this operation is performed in a trusted environment
where people don't have access to the private keys or sensitive input files.

    gpg --output signed-and-encrypted.pgp \
      --sign --digest-algo SHA384 \
      --encrypt --cipher-algo AES256 \
      --armor \
      --recipient {key_id} \
      input.txt

GPG will automatically select the right key from the bundle for each operation
you ask it to perform.

## JWE encryption with JWS signing

JSON Web Encryption (JWE) is a standard defined by [rfc7516](https://tools.ietf.org/html/rfc7516) for encrypting content at the application
level. JSON Web Signature (JWS) is a standard defined by
[rfc7515](https://tools.ietf.org/html/rfc7515) for signing content at the
application level.

Requests and responses will be JWE tokens encrypted using asymmetric (public
key) encryption with the "Compact Serialization" option. The JWE token will
contain the signed payload as a JWS token. JWS also uses asymmetric keys;
private key for signing and public key for verification.

When sending a payload, sign the payload first and then encrypt it. When
receiving a payload, decrypt it first and then verify the signature.

When using JWE, Partners must support the following options:

- Compact Serialization.
- Decrypting payloads from one of multiple JWE keys.
- The RSA-OAEP, RSA-OAEP-256, or ECDH-ES algorithm for key management.
  - Populated in the `alg` header ([rfc7518 section 4.1](https://datatracker.ietf.org/doc/html/rfc7518#section-4.1)).
- The [A256GCM](https://datatracker.ietf.org/doc/html/rfc7518#section-5.3), [A128GCM](https://datatracker.ietf.org/doc/html/rfc7518#section-5.3), [A128CBC-HS256](https://tools.ietf.org/html/rfc7518#section-5.2.3), or [A256CBC-HS512](https://tools.ietf.org/html/rfc7518#section-5.2.5) algorithm for content encryption.
  - Populated in the `enc` header.
- `kid` header to identify the public encryption key.
- Message payloads that use JWE encryption must use the content type application/jose; charset=utf-8.

When using JWS, Partners must support the following options:

- Compact Serialization.
- Verifying payloads from one of multiple JWS keys.
- The HS256, HS384, HS512, RS256, RS384, RS512, ES256, PS256, PS384, or PS512 algorithm for signature creation.
  - Populated in the `alg` header ([rfc 7518 section 3.1](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1)).
- `kid` header to identify the private signing key.

JWE/JWS strings will be encoded as UTF-8 strings and their payloads may be
arbitrary bytes.

Private keys must be RSA/ECDH-ES keys that expire in one year with a max
lifetime of two years. All private key identities must always stay on the
partner's server and, accordingly, all signature values must be calculated on
the partner's server.

Before beginning development you need to exchange JWE and JWS keys with Google.
Keys should be exchanged in JWK format, as defined in
[rfc7517](https://datatracker.ietf.org/doc/html/rfc7517).
In this step, you generate a public-private key pair, provide the public
key to Google, and receive a public key back from Google. During development,
you will only need to exchange sandbox keys used for development and testing
outside of production. Before production testing and launch, you will need to
perform another exchange of production keys.