Skip to content

Commit

Permalink
Update cryptoV2 adr
Browse files Browse the repository at this point in the history
  • Loading branch information
raynaudoe committed Feb 9, 2024
1 parent 974b482 commit ef09a84
Showing 1 changed file with 77 additions and 83 deletions.
160 changes: 77 additions & 83 deletions docs/architecture/adr-071-cryptography-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Change log

* Feb 8th 2024: Fixes and improvements (Zondax AG: @raynaudoe @juliantoledano @jleni @educlerici-zondax)
* Nov 1st 2023: Initial Draft (Zondax AG: @raynaudoe @bizk @juliantoledano @jleni @educlerici-zondax)

## Status
Expand All @@ -10,15 +11,16 @@ DRAFT

## Abstract

This ADR proposes a refactor of the crypto module to enhance modularity, re-usability, and maintainability,
while prioritizing developer experience and incorporating best security practices.
This ADR proposes the creation of a new crypto module (**cryptoV2** from now on) to enhance the modularity, re-usability, and maintainability
of all the crypto tools and algorithms available in the sdk while prioritizing developer experience and incorporating best security practices.
The proposal defines a clear division of scope for each component, cleaner interfaces, easier extension,
better test coverage and a single place of truth, allowing the developer to focus on what's important
while ensuring the secure handling of sensitive data throughout the module.
while ensuring the secure handling of sensitive data throughout the module. Lastly but not least allowing the ecosystem to
grow and implement new cryptographic methods and tools as easy as possible.

## Introduction

This ADR outlines the redesign and refactoring of the crypto package. The design establishes a clear decoupling via interfaces, extension points, and a much more modular design to allow developers to concentrate on application level aspects while ensuring the adequate handling of sensitive data.
This ADR outlines the redesign of the crypto package. The design establishes a clear decoupling via interfaces, extension points, and a much more modular design to allow developers to concentrate on application level aspects while ensuring the adequate handling of sensitive data.

Special focus has been placed on the following key aspects:

Expand All @@ -28,36 +30,32 @@ Special focus has been placed on the following key aspects:
* maintainability
* developer experience

The proposal determines a clear decoupling via interfaces, additional extension points, and a much more modular design to allow developers to application level aspects while ensuring the secure handling of sensitive data when applying this SDK.

The enhancements in this proposal not only render the ["Keyring ADR"](https://github.com/cosmos/cosmos-sdk/issues/14940) obsolete, but also encompass its key aspects, replacing it with a more flexible and comprehensive approach. Furthermore, the gRPC service proposed in the Keyring ADR can be easily implemented as a specialized implementation of the "CryptoProvider" interface defined later in this ADR. This allows for the integration of HashiCorp-like [go-plugins](https://github.com/hashicorp/go-plugin) over gRPC, providing a robust and extensible solution for keyring functionality.

Furthermore, the grpc service proposed in the Keyring ADR can be easily followed by creating an implementation of the "CryptoProvider" interface defined in this ADR. This allows for the integration of HashiCorp plugins over gRPC, providing a robust and extensible solution for keyring functionality.

By deprecating the previous ADR and introducing these enhancements, the new ADR offers a more comprehensive and adaptable solution for cryptography and address management within the Cosmos SDK ecosystem.
Furthermore, the grpc service proposed in the Keyring ADR can be easily followed by creating an implementation of the "CryptoProvider" interface defined in this ADR. This allows, for example, the integration of HashiCorp plugins over gRPC, providing more flexible implementations.

### Glossary

1. **Interface**: In the context of this document, "interface" refers to Go's interface concept.

2. **Module**: In this document, "module" refers to a Go module. The proposed ADR focuses on the Crypto module V2, which suggests the introduction of a new version of the Crypto module with updated features and improvements.
2. **Module**: In this document, "module" refers to a Go module.

3. **Package**: In the context of Go, a "package" refers to a unit of code organization. Each proposed architectural unit will be organized into packages for better reutilization and extension.
3. **Package**: In the context of Go, a "package" refers to a unit of code organization.

## Context

In order to fully understand the need for changes and improvements to the cryptographic package, it's crucial to consider the current state of affairs:
In order to fully understand the need for changes and the proposed improvements, it's crucial to consider the current state of affairs:

* The Cosmos SDK currently lacks a comprehensive ADR for the cryptographic package.
* Type leakage outside the current crypto module pose backward compatibility and extensibility challenges.
* Type leakage of specific crypto data types expose backward compatibility and extensibility challenges.
* The demand for a more flexible and extensible approach to cryptography and address management is high.
* Architectural changes are necessary to resolve many of the currently open issues.
* There is a current trend towards modularity in the Interchain stack (e.g. runtime modules)
* Security implications are a critical consideration during the redesign work.

## Objectives

The key objectives for the Cryptography v2 module are:
The key objectives for the CryptoV2 module are:

Modular Design Philosophy

Expand Down Expand Up @@ -155,6 +153,10 @@ Through each Crypto provider, users can access functionality such as signing, ve

By abstracting the underlying cryptographic functionality, *Crypto providers* enable a modular and extensible architecture. It allows users to easily switch between different cryptographic implementations without impacting the rest of the system.

A `CryptoProvider` can be built from different sources, such as a `SecureItem`, a randomness source, a seed, a mnemonic, or a string.
Since the underlying representation of a `CryptoProvider` is a protobuf message, it can be easily serialized and stored in a safe manner.
The storing and retrieval is handled by a `SecureStorage` implementation which will be presented in the next section.

```go
type ProviderMetadata interface {
key string
Expand Down Expand Up @@ -192,7 +194,7 @@ type ICryptoProvider interface {

#### Signing

Interface responsible for Signing a message and returning the generated Signature.
Interface responsible for signing a message and returning the generated signature.

```go
type ISigner interface {
Expand Down Expand Up @@ -232,19 +234,20 @@ type IHasher interface {
}
```

### StorageProvider

### Secure Storage

A *Secure Storage* represents a secure vault where one or more *Secure Items* can be stored. It serves as a centralized repository for securely storing sensitive data. To access a *Secure Item*, users must interact with the *Secure Storage*, which handles the retrieval and management of keys.
A *Secure Storage* represents a secure vault where one or more *Secure Items* can be stored. As a parallelism, a `SecureStorage` instance can be compared to the current `Keyring Backend` interface,
but with the main difference that the stored items are abstracted as `SecureItem` instead of `Record`. This allows a fully decoupled relation between what is being stored (`SecureItem`) and where it is being stored (`SecureStorage`).
To access a *Secure Item*, users must interact with the *Secure Storage*, which handles the retrieval and management of keys.
Different implementations of *Secure Storage* will be available to cater to various storage requirements:

* FileSystem: This implementation stores the Secure Items in a designated folder within the file system.
* Memory: This implementation stores the Secure Items in memory, providing fast access but limited persistence.
* FileSystem: This implementation stores the items in a designated folder within the file system.
* Memory: This implementation stores the items in memory, providing fast access but limited persistence (for testing purpose mainly).
* KMS: This implementation utilizes the Key Management System available on AWS, GCP, etc.
* others: 1password, OS-integrated secure storage (macOS, Linux, Windows, etc.)
* others: 1password, OS-integrated secure storage (macOS, Linux, Windows)

```go
type IStorageProvider interface {
type ISecureStorage interface {
List() []string

Get(name string) (SecureItem, error)
Expand All @@ -253,34 +256,35 @@ type IStorageProvider interface {
}
```

### Secure Item

A *Secure Item* is a structured data object designed for storing any type of data within a *Secure Storage* instance.
In the context of this ADR, the **Blob** field of a Secure Item represents a "recipe" or blueprint for constructing the corresponding *Crypto Provider*.
The **Blob** can be encoded in any format and should contain all the necessary configuration information required to instantiate the specific cryptographic packages that compose the *Crypto Provider*.
In the context of this ADR, the `Blob` field of a `SecureItem` represents the serialized form of a `CryptoProvider`.

_Note:_ The encoder/decoder of the `Blob` field will be dependent on the `CryptoProvider` implementation, a `SecureItem`
has no knowledge of the underlying data structure.

```go
type ISecureItemMetadata interface {
Type() TypeUUID // Relates to the corresponding provider
Name() string
...
}

type ISecureItem interface {
ISecureItemMetadata

// Blob format/encoding will be dependant of the CryptoProvider implementation
Bytes() []byte
}
```

##### Keyring

*Keyring* serves as a central hub for managing *Crypto Providers* and *Secure Storage* implementations. It provides methods to register *Crypto Providers* and *Secure Storage* implementations.
The **RegisterCryptoProvider** function allows users to register a Crypto Provider blueprint by providing its unique identifier and a builder function. Similarly, the **RegisterSecureStorage** function enables users to register a secure storage implementation by specifying a unique identifier and a builder function.

The `Keyring` interface serves as a central hub for managing `CryptoProviders` and `SecureStorage` implementations.
The main difference with the current `Keyring` interface is that it adds the ability to register several `SecureStorage` (this is, several "storing backends") implementations and the
_values_ are abstracted as `SecureItem` instead of `Record`.

```go
type IKeyring interface {
RegisterCryptoProvider(typeUUID TypeUUID, builder CryptoProviderBuilder)
RegisterCryptoProviderBuilder(typeUUID TypeUUID, builder CryptoProviderBuilder)
RegisterAndLoadStorageProvider(typeUUID TypeUUID, provider StorageProvider)

ListStorageProviders() ([]IStorageProvider, error)
Expand All @@ -294,14 +298,13 @@ type IKeyring interface {

#### **Wallet**

The Wallet interface contains the blockchain specific use cases of the crypto module. It also serves as an API for:
The `Wallet` interface contains the blockchain specifics logics for converting PubKeys into addresses.
It also serves as a convenient API for:

* Signing and Verifying messages.
* Signing and Verifying messages
* Generating addresses out of keys

Since wallet interacts with the user keys, it contains an instance of the Keyring, it is also where the blockchain specific logic should reside.

Note: Each Wallet implementation should provide the logic to map addresses and ItemIds
_Note:_ Each Wallet implementation should provide the logic to map addresses and PubKeys.

```go
type Wallet interface {
Expand All @@ -316,17 +319,16 @@ type Wallet interface {

##### **Blob**

This is a wrapper for the widely used `[]byte` type that is used when handling binary data. Since crypto module handles sensitive information, the objective is to provide some extra security capabilities around such type as:
This is a wrapper for the widely used `[]byte` type that is used when handling binary data.
Since handling sensitive information is a common task in crypto algorithms, the objective is to provide some extra security capabilities around such type as:

* Zeroing values after a read operation.
* Proper data handling.

These blob structures would be passed within components of the crypto module. For example: Signature information

#### **Keys**
#### **Pub/Priv Key**

A key object is responsible for containing the **BLOB** key information. Keys might not be passed through functions, and it is
suggested to interact through crypto providers to limit the exposure to vulnerabilities.
PubKey and PrivKey are wrappers to store the corresponding keys bytes.
The corresponding implementations will have the proper security measures to handle the keys mentioned at the beginning of this document.

```mermaid
classDiagram
Expand All @@ -338,14 +340,6 @@ classDiagram
PrivKey : key
```

Base Key struct

```go
type KeyStruct struct {
key Blob
}
```

Base key interface (common to private and public keys)

```go
Expand All @@ -372,16 +366,6 @@ type PrivKey interface {
}
```

#### Signatures

A signature consists of a message/hash signed by one or multiple private keys. The main objective is to authenticate a message signer through their public key.

```go
type Signature struct {
data Blob
}
```

**Flow overview**

***Initialization***
Expand Down Expand Up @@ -457,34 +441,44 @@ granularity.

We will:

* Refactor module structure as described above.
* Refactor the module structure as described above.
* Define types and interfaces as the code attached.
* Refactor existing code into new structure and interfaces.
* Implement Unit Tests to ensure no backward compatibility issues.

## Consequences
## Consequences

### Impact on the SDK codebase

This ADR primarily impacts the client-side components of the Cosmos SDK. The consensus layer of the Cosmos SDK, which Tendermint Core largely handles, will not be directly affected by these changes. The cryptographic tools, such as hashers and verifiers, will still be available as external packages. These can be imported and utilized directly in the consensus code without the need for a CryptoProvider instance. This approach ensures that the consensus layer remains decoupled from the specific implementations of cryptographic operations. It maintains the integrity and stability of the consensus process while allowing for enhancements and extensions in the cryptographic functionalities.
We can divide the impact of this ADR into two main categories: state machine code and client related code.

#### Client

The major impact will be on the client side, where the current `Keyring` interface will be replaced by the new `Wallet` and `Keyring` interfaces.
This means that any piece of code that makes use of the `Record` struct will need to be adapted to use the new `CryptoProvider` instead.
This will aso affect a large number of unit tests that will need to be adapted/replaced with new ones.

#### State Machine

The impact on the state machine code will be minimal, the only module affected (at the time of writing this ADR)
is the `x/accounts` module, specifically the `Authenticate` function. This function will need to be adapted to use a `CryptoProvider` service to make use of the `Verifier` instance.
As a result, the account abstraction feature will benefit from all the new features and security improvements mentioned in this ADR.


_Note:_ All the cryptographic tools (hasher, verifier, signer, etc) will still be available as standalone packages that can be
imported and utilized directly without the need for a `CryptoProvider` instance. But, the `CryptoProvider` will be the recommended way to use them
since it provides a more secure way to handle sensitive dta, better modularity and the possibility to store configurations and metadata into the CryptoProvider
definition.


### Backwards Compatibility

Some packages will need a medium to heavy refactor to be compatible with this ADR.
In short, packages using _Keyring_ (current SDK) will need to be adapted to use the new Keyring and CryptoProvider interfaces.
Other special cases where a refactor will be needed, are the ones that make use crypto components in isolation like the _PrivateKey_ and _PublicKey_ structs
to sign and verify transactions respectively.

As first approach, the most affected packages are:
- crypto/types
- client/rpc
- client/tx
- client/keys
- types/tx/signing
- x/auth
- x/auth/client
- x/slashing
- simapp/simd
The proposed migration path is similar to what the cosmos-sdk has done in the past. To ensure a smooth transition, the following steps will be taken:
- Create a new package `cryptoV2` and implement this ADR. Create unit tests, documentation and examples.
- Deprecate the old crypto package. The old crypto package will still be usable, but it will be marked as deprecated and users can opt to use the new package.
- Migrate the codebase to use the new `CryptoV2` package and remove the old crypto package.

_A more detailed migration path is provided in the corresponding document._

### Positive

Expand All @@ -509,7 +503,7 @@ As first approach, the most affected packages are:
## Test Cases

*The code will be unit tested to ensure a high code coverage
- There should be integration tests around Wallet, keyring and crypto providers.
- There should be integration tests around Wallet, Keyring and CryptoProviders.
- There should be benchmark tests for hashing, keyring, encryption, decryption, signing and verifying functions.

## Further Discussions
Expand Down Expand Up @@ -539,8 +533,8 @@ As first approach, the most affected packages are:

### Tentative Primitive Building Blocks

This is a tentative list of primitives that we might want to support.
This is not a final list or comprehensive, and it is subject to change.
This is a tentative list of primitives that we might want to support.
This is not a final list or comprehensive, and it is subject to change.
Moreover, it is important to emphasize the purpose of this work allows extensibility so any other primitive can be added in the future.

* digital signatures
Expand All @@ -562,8 +556,8 @@ Moreover, it is important to emphasize the purpose of this work allows extensibi

* Hashing
* sha2 / sha3
* RIPEMD-160
* RIPEMD-160
* blake2b,2s,3
* Keccak-256 / shake256
* bcrypt / scrypt / argon2, Argon2d/i/id
* Pedersen
* Pedersen

0 comments on commit ef09a84

Please sign in to comment.