encid

package module
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2024 License: MIT Imports: 10 Imported by: 0

README

Encid - encode and decode encrypted integer IDs

Go Reference Go Report Card Tests Coverage Status Mentioned in Awesome Go

This is encid, a program and library for working with encrypted integer IDs.

The main use case is when you have a database that assigns consecutive integer IDs to resources and you need to expose them publicly without revealing the actual values.

For example, suppose you have a web-based service that handles URLs of the form https://example.com/profile?user=17 for showing the profile page of a user. This URL allows an attacker to guess other valid profile URLs (e.g., https://example.com/profile?user=1, https://example.com/profile?user=2, etc.), reveals that this user is probably the 17th one to have signed up, suggests a possible relationship between users with ids close to each other, and via scraping can expose your total number of users (e.g., if there’s no https://example.com/profile?user=18, you’ve probably got only 17 users).

On the other hand, if your service’s profile URLs look like https://example.com/profile?user=7pWwPc2rWTzsZX85s9KFgRW, there is no way for an attacker to guess that the consecutively next profile URL is https://example.com/profile?user=bgnnCXYybm7q5FshMN4xYRT or to tell how close or far apart they are or to scrape all your profile URLs or to know how many users you have.

Installation and usage

For library usage please see the Godoc.

To install the CLI:

go install github.com/bobg/encid/cmd/encid@latest

Command-line usage:

encid [-keystore FILE] enc [-50] TYPE NUM
encid [-keystore FILE] dec [-50] ID STR
encid [-keystore FILE] newkey TYPE

The -keystore flag specifies the path to a database containing cipher keys for encrypting and decrypting IDs. By default this lives under the encid directory in os.UserConfigDir().

Each cipher key is associated with an integer “type” whose meanings are user-defined. You may choose to give all your keys the same type, or you might prefer to use different types for different resources (e.g. 1 for users, 2 for documents, etc).

In enc mode, you specify a type and a number to encode. You get back a “key ID” and the encoded string. The latest cipher key for the given type is used. If no cipher key exists in the keystore for the given type, one is created.

$ encid enc 1 17
4 d7w90xn4pfk9rfqw9d4wc0zdn0

In dec mode, you specify a key ID and an encoded string. You get back a type and the decoded number.

$ encid dec 4 d7w90xn4pfk9rfqw9d4wc0zdn0
1 17

In newkey mode, you specify a type. A new random cipher key with that type is added to the keystore.

The encoding uses base 30 by default. The -50 flag causes base 50 to be used instead. For more information about these encodings please see basexx.

Documentation

Overview

Package encid provides a mechanism for working with encrypted integer IDs.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is the type of error produced when KeyStore methods find no key.

Functions

func Decode

func Decode(ctx context.Context, ks KeyStore, keyID int64, inp string) (int, int64, error)

Decode decodes a keyID/string pair produced by Encode. It produces the type of the key that was used, and the bare int64 value that was encrypted. As a convenience, it maps the input string to all lowercase before decoding.

If the keystore is also a Versioner that reports a version of 2 or greater, the input string must use version-2 encoding (i.e., it must have been produced with a keystore that also reports a version of 2 or greater). See https://github.com/bobg/encid/issues/5.

func Decode50

func Decode50(ctx context.Context, ks KeyStore, keyID int64, inp string) (int, int64, error)

Decode50 decodes a keyID/string pair produced by Encode50. It produces the type of the key that was used, and the bare int64 value that was encrypted. Unlike Decode, this does not map the input to lowercase first, since base50 strings are case-sensitive.

If the keystore is also a Versioner that reports a version of 2 or greater, the input string must use version-2 encoding (i.e., it must have been produced with a keystore that also reports a version of 2 or greater). See https://github.com/bobg/encid/issues/5.

func Encode

func Encode(ctx context.Context, ks KeyStore, typ int, n int64) (int64, string, error)

Encode encodes a number n using a key of the given type from the given keystore. The result is the ID of the key used, followed by the encrypted string. The encrypted string is expressed in base 30, which uses digits 0-9, then lower-case bcdfghjkmnpqrstvwxyz. It excludes vowels (to avoid inadvertently spelling naughty words) and lowercase "L".

If the keystore is also a Versioner that reports a version of 2 or greater, the resulting string will use a different encoding than in earlier versions and can be decoded only with a keystore that also reports a version of 2 or greater. See https://github.com/bobg/encid/issues/5.

func Encode50

func Encode50(ctx context.Context, ks KeyStore, typ int, n int64) (int64, string, error)

Encode50 is the same as Encode but it expresses the encrypted string in base 50, which uses digits 0-9, then lower-case bcdfghjkmnpqrstvwxyz, then upper-case BCDFGHJKMNPQRSTVWXYZ.

If the keystore is also a Versioner that reports a version of 2 or greater, the resulting string will use a different encoding than in earlier versions and can be decoded only with a keystore that also reports a version of 2 or greater. See https://github.com/bobg/encid/issues/5.

Types

type KeyStore

type KeyStore interface {
	// DecoderByID looks up a key in the store by its ID.
	// It returns the key's type and a function for decrypting a data block using the key.
	// The slice arguments to the decryption function must overlap entirely or not at all.
	// If no key with the given ID is found,
	// ErrNotFound is returned.
	DecoderByID(context.Context, int64) (int, func(dst, src []byte), error)

	// EncoderByType looks up a key in the store by its type.
	// It returns the key's ID and a function for encrypting a data block using the key.
	// The slice arguments to the encryption function must overlap entirely or not at all.
	// In case there are multiple keys of the given type,
	// it is up to the implementation to choose one and return it.
	// If no key with the given type is found,
	// ErrNotFound is returned.
	EncoderByType(context.Context, int) (int64, func(dst, src []byte), error)
}

KeyStore is an object that stores encryption keys. Each key is 16, 24, or 32 bytes long, and has an associated "type" (an int) and a unique key ID (an int64). These keys can be used to encrypt other int64s, and to decrypt the resulting strings. See Encode and Decode.

If you're implementing a KeyStore, you should also implement the Versioner interface, and return a value of 2 or greater from the Version method. A KeyStore that isn't also a Versioner is assumed to be at version 1.

type Versioner added in v1.5.0

type Versioner interface {
	Version() int
}

Versioner is an optional interface that KeyStores should implement. It reports the version of the encoding to use when using a KeyStore.

When the KeyStore is a Versioner reporting version 2 or later, a different encoding is used to make the results more secure. See https://github.com/bobg/encid/issues/5.

If a KeyStore does not implement Versioner, it is assumed to be at version 1.

Version 2 encoded IDs are not compatible with version 1 IDs; you can't decode a v2 ID using a v1 KeyStore and vice versa.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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