dvx

package module
v0.0.0-...-b6677e2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2021 License: Apache-2.0 Imports: 11 Imported by: 0

README

dvx

Package dvx provides an easy-to-use interface to a Cryptography service, that uses state-of-the-art primitives. It provides 4 main categories of supported operations: Encryption/Decryption, Signing/Verifying, MAC, and as a special higher-order algorithm: TOTP Creation/Verification.

Picture of schematic architecture (See the picture of the complete architecture here)

Specification

Encoding

dvx has built-in support for upgrading the underlying cryptographic primitives used. It therefore introduces its packaging format for results from a dvx.Protocol instance:

<version>.<type_prefix>.<data>
  1. Version: Is the version of the underlying primitives and the way how keys are derived from the KeyPool for there respective primitives.
  2. TypePrefix: Is the identifier of the module used: "enc", "sig", "tag" or "totp"
  3. Data: is the raw data (e.g. encrypted content, signature, mac tag, etc.) represented as base64 url string without padding append ("Raw" encoding).
Primitives
dv1
  • Authenticated Encryption: XChaCha20-Poly1305 (192-bit random nonce, 256-bit key, 128-bit authentication tag)
    1. Generate 24 random bytes using a CSPRNG as nonce
    2. Pack "dv1" version string and nonce into AEAD-additional data (append([]byte("dv1"), nonce...))
    3. Use AEAD construction with key, nonce, message, additional_data
  • MAC: Keyed Blake2b (512-bit key, 256-|512-bit tag)
  • Signatures: Ed25519 (EdDSA over Curve25519)
  • Key Derivation: Argon2id (512-bit derived key)
Further reading

A few links and resources that should explain why the selected primitives where chosen for dv1

Documentation

Overview

Package dvx provides an easy-to-use interface to a Cryptography service, that uses state-of-the-art primitives. It provides 4 main categories of supported operations: Encryption/Decryption, Signing/Verifying, MAC, and as a special higher-order algorithm: TOTP Creation/Verification.

Goals

1. No storage needed

dvx doesn't need any storage, as it derives all internal keys from a root secret. This root secret can live inside a hardware-security-module (HSM via PKCS#11) or as an alternative be held in a protected RAM section.

2. Hard to misuse

dvx has an easy-to-use interface and clear separation (boundaries) of liabilities.

Index

Constants

View Source
const (
	// Version is the version header of the current Protocol implementation. It
	// is the lower-cased string name of the underlying Primitive.
	Version string = "dv1"
)

Variables

This section is empty.

Functions

func DecodeExpect

func DecodeExpect(s string, expected TypePrefix) (version string, data []byte, err error)

DecodeExpect is like Decode, but additionally verifies that the decoded TypePrefix matches the expected TypePrefix. If they match the TypePrefix is removed from the result, otherwise an error is returned.

func Encode

func Encode(typePrefix TypePrefix, data []byte) string

Encode encodes a TypePrefix and associated data according to the current major DVX version (DV1)

Types

type DV1

type DV1 struct {
}

func (DV1) Decrypt

func (d DV1) Decrypt(key []byte, cipher []byte) (data []byte, err error)

func (DV1) Encrypt

func (d DV1) Encrypt(key []byte, data []byte) (cipher []byte, err error)

func (DV1) KDF512

func (d DV1) KDF512(password []byte, salt []byte) (key []byte, err error)

func (DV1) MAC256

func (d DV1) MAC256(key []byte, message []byte) (tag []byte, err error)

func (DV1) MAC512

func (d DV1) MAC512(key []byte, message []byte) (tag []byte, err error)

func (DV1) Sign

func (d DV1) Sign(privateKey []byte, message []byte) (signature []byte, err error)

func (DV1) Verify

func (d DV1) Verify(publicKey []byte, message []byte, signature []byte) (valid bool, err error)

type KeyPool

type KeyPool interface {
	// KDF32 is a key derivation function that returns a 32-byte key for the
	// keyRing passed to it. Equal keyRings must always result in equal keys.
	KDF32(keyRing []byte) (key []byte, err error)
	// KDF64 is a key derivation function that returns a 64-byte key for the
	// keyRing passed to it. Equal keyRings must always result in equal keys.
	KDF64(keyRing []byte) (key []byte, err error)
	// Close closes the KeyPool and it's underlying instances.
	Close() error
}

KeyPool is an interface for a key derivation loader.

func WrapDVXAsKeyPool

func WrapDVXAsKeyPool(dvx Primitive, rootKey []byte, log logger.Logger) KeyPool

WrapDVXAsKeyPool provides a KeyPool implementation by using the Primitive.MAC256 and Primitive.MAC512 functions as key-derivation-functions. The passed rootKey is used as key for the MAC-constructions. A passed keyRing is used a message during derivation.

type Primitive

type Primitive interface {
	KDF512(password []byte, salt []byte) (key []byte, err error)
	MAC256(key []byte, message []byte) (tag []byte, err error)
	MAC512(key []byte, message []byte) (tag []byte, err error)
	Encrypt(key []byte, data []byte) (cipher []byte, err error)
	Decrypt(key []byte, cipher []byte) (data []byte, err error)
	Sign(privateKey []byte, message []byte) (signature []byte, err error)
	Verify(publicKey []byte, message []byte, signature []byte) (valid bool, err error)
}

Primitive is a low level cryptographic contract.

type Protocol

type Protocol struct {
	// contains filtered or unexported fields
}

Protocol is an implementation of the current major dvx version. It can decrypt and verify ciphers, signatures and tags from all previous major versions.

This means the Protocol implementation under azoo.dev/utils/dvx will always use DV1 as it's Primitive. When DV2 will eventually get released, it will be hosted under azoo.dev/utils/dvx/v2, and it's Protocol will use DV2 as it's Primitive, but will be able to decrypt and verify DV1 content.

The interface of Protocol is closely tied to that of Dragon (originally it's parent project), but may be used directly in non-Dragon scenarios or to locally verify signatures (VerifyPK) without the need to contact a Dragon server.

func NewProtocol

func NewProtocol(keyPools map[string]KeyPool) *Protocol

NewProtocol creates a new Protocol from a map of KeyPool. The map specifies different KeyPool for major DVX versions.

Therefore, a valid map would be:

map[string]dvx.KeyPool{
  dvx.Version: dvx.WrapDVXAsKeyPool(dvx.DV1{}, []byte{}),
}

func (*Protocol) CreateSignKey

func (p *Protocol) CreateSignKey(keyRing string) (publicKey []byte, err error)

CreateSignKey derives a private key using the keyRing and returns its public key counterpart to the caller. It can be used in conjunction with VerifyPK to verify signatures created with Sign using the same keyRing.

func (*Protocol) Decrypt

func (p *Protocol) Decrypt(keyRing string, ciphertext string) (data []byte, err error)

Decrypt derives a secret key `sk` using the keyRing and subsequently decrypts ciphertext using `sk`.

func (*Protocol) Encrypt

func (p *Protocol) Encrypt(keyRing string, data []byte) (ciphertext string, err error)

Encrypt derives a secret key `sk` using the keyRing and subsequently encrypts data using `sk`.

func (*Protocol) GenerateTOTP

func (p *Protocol) GenerateTOTP(keyRing string, issuer string, accountName string, accountID string) (id string, uri string, err error)

GenerateTOTP derives a secret key `sk` using the keyRing. Afterwards, it generates 32 random bytes `raw-id`, which are encoded to a totp-id using Encode with a TOTP TypePrefix. Subsequently, `sk` and `raw-id` are used to derive an intermediate key `i`, which is mixed with an `accountID` to cryptographically bind the final totp-secret-key `totp-sk` to a specific end-user account.

The `totp-sk` secret used for totp calculations has 32 bytes and SHA256 is selected as a totp algorithm. Moreover, digits and period are left to their defaults: 6 and 30 respectively.

The returned `id` must be stored by the caller in order to VerifyTOTP codes in the future. NO additional integrity checks/measurements are needed in storage to protect from id-swapping attacks, as `account-id` is cryptographically bound and `totp-sk` depends on it. Although the returned `id` is useless in itself, it should not be returned to the end-user client.

The returned uri is a Google Authenticator compliant URI string (https://github.com/google/google-authenticator/wiki/Key-Uri-Format) that can be used by end-users to set up an authenticator. It can be directly passed to azoo.dev/utils/qr generator to create a QR-image of the uri for easy end-user set up.

func (*Protocol) MAC

func (p *Protocol) MAC(keyRing string, message []byte) (tag string, err error)

MAC derives a secret key `sk` using the keyRing and subsequently calculates a MAC tag of data using `sk`.

func (*Protocol) Sign

func (p *Protocol) Sign(keyRing string, message []byte) (signature string, rawSignature []byte, err error)

Sign derives a private key using the keyRing and subsequently calculates a signature for data.

func (*Protocol) Verify

func (p *Protocol) Verify(keyRing string, message []byte, signature string) (valid bool, err error)

Verify derives a private key using the keyRing and subsequently uses its public key counterpart to verify the signature for data.

func (*Protocol) VerifyPK

func (p *Protocol) VerifyPK(publicKey []byte, message []byte, signature string) (valid bool, err error)

VerifyPK uses the provided public key directly to verify the signature for data. VerifyPK doesn't derive any key from the internal KeyPool and is safe to use for Protocol objects with empty KeyPool maps. It can be used verify a DVX signature string without access to the KeyPool and respectively private key counterparts.

func (*Protocol) VerifyTOTP

func (p *Protocol) VerifyTOTP(keyRing string, id string, accountID string, code string) (valid bool, err error)

VerifyTOTP derives a totp-secret-key `totp-sk` using the same procedure as described in GenerateTOTP and subsequently uses it to verify the provided code in constant-time.

type TypePrefix

type TypePrefix string

TypePrefix is a string defining the prefix of the encoded dvx string

const (
	// Encrypted is the TypePrefix for encrypted content
	Encrypted TypePrefix = "enc"
	// Signed is the TypePrefix for a signature
	Signed TypePrefix = "sig"
	// Tagged is the TypePrefix for a MAC
	Tagged TypePrefix = "tag"
	// TOTP is the TypePrefix for a TOTP selector id
	TOTP TypePrefix = "totp"
)

func Decode

func Decode(s string) (version string, typePrefix TypePrefix, data []byte, err error)

Decode decodes a DVX string s into it's major version, TypePrefix, associated data. If any errors occur Decode returns a descriptive error.

Directories

Path Synopsis
hsm module
tearc module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL