presents

package module
v0.0.0-...-2f78e69 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2018 License: MIT Imports: 9 Imported by: 0

README

presents

GoDoc Build Status codecov Go Report Card

Like hashids, but based on block ciphers.

Inspired by this StackOverflow answer suggesting using a block cipher to obfuscate IDs.

How it works

The PRESENT block cipher [1] operates on 8-byte (64-bit) blocks and supports key lengths of 80-bits or 128-bits. It can be used to create a reversible mapping from 64-bit integers to 64-bit integers.

The resultant 64-bit integer is then converted to and from a string using an arbitrary change of base algorithm and a provided alphabet.

Triple DES, which also has a 64-bit block size, can be used as well.

Usage

package main

import (
	"fmt"
	"log"

	"github.com/yi-jiayu/presents"
)

func main() {
	// 80-bit PRESENT block cipher key
	key := make([]byte, 10)
	p, err := presents.New(key, nil)
	// with 3DES instead of PRESENT
	// key := make([]byte, 24)
	// p, err := presents.NewTripleDES(key, nil)
	if err != nil {
		log.Fatal(err)
	}

	s := p.Wrap(1213486160)
	fmt.Println(s) // 90NyXHLckhA

	n, err := p.Unwrap(s)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(n) // 1213486160
}

Performance

Some benchmarks on my i5-7200U:

$ go test -bench . -benchtime 10s
goos: windows
goarch: amd64
pkg: github.com/yi-jiayu/presents
BenchmarkPresents_Wrap-4                 1000000             10344 ns/op
BenchmarkPresentsTripleDES_Wrap-4       20000000               621 ns/op
BenchmarkPresentsBlowFish_Wrap-4        50000000               347 ns/op
PASS
ok      github.com/yi-jiayu/presents    41.590s

References

  1. Bogdanov A. et al. (2007) PRESENT: An Ultra-Lightweight Block Cipher. In: Paillier P., Verbauwhede I. (eds) Cryptographic Hardware and Embedded Systems - CHES 2007. CHES 2007. Lecture Notes in Computer Science, vol 4727. Springer, Berlin, Heidelberg (pdf)

Documentation

Overview

Package presents implements a block cipher-based method of converting 64-bit unsigned integers to and from strings.

The intended application is towards the obfuscation of sequential database IDs.

Example

This example show how to encode and decode IDs.

package main

import (
	"fmt"
	"log"

	"github.com/yi-jiayu/presents"
)

func main() {
	// 80-bit PRESENT block cipher key
	key := make([]byte, 10)
	p, err := presents.New(key, nil)
	if err != nil {
		log.Fatal(err)
	}

	s := p.Wrap(1213486160)
	fmt.Println(s)

	n, err := p.Unwrap(s)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(n)
}
Output:

90NyXHLckhA
1213486160
Example (CustomAlphabet)

This example shows how to use a custom alphabet as well as shuffling it.

package main

import (
	"fmt"
	"log"

	"github.com/yi-jiayu/presents"
)

func main() {
	// 80-bit PRESENT block cipher key
	key := make([]byte, 10)
	options := &presents.Options{
		Alphabet: "_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
		Shuffle:  true,
		Seed:     12,
	}
	p, err := presents.New(key, options)
	if err != nil {
		log.Fatal(err)
	}

	s := p.Wrap(1213486160)
	fmt.Println(s)

	n, err := p.Unwrap(s)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(n)
}
Output:

tiKYxtU_2ZB
1213486160

Index

Examples

Constants

View Source
const DefaultAlphabet = alphabet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")

DefaultAlphabet contains printable characters from 0-9, A-Z and a-z, similar to a base62 encoding.

Variables

This section is empty.

Functions

This section is empty.

Types

type Options

type Options struct {
	Alphabet string
	Shuffle  bool
	Seed     int64
}

Options can be passed to New to customise the alphabet to be used.

type Presents

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

Presents contains a cipher.Block implementing PRESENT and an alphabet for converting between 64-bit integers and strings.

func New

func New(key []byte, options *Options) (*Presents, error)

New creates a new Presents struct using the PRESENT block cipher. If options.Alphabet is not the empty string, it will be used as the alphabet. If options.Shuffle is true, the alphabet will be shuffled based on options.Seed.

func NewTripleDES

func NewTripleDES(key []byte, options *Options) (*Presents, error)

NewTripleDES creates a new Presents struct using Triple DES instead of PRESENT. If options.Alphabet is not the empty string, it will be used as the alphabet. If options.Shuffle is true, the alphabet will be shuffled based on options.Seed.

Example

This example shows how to use the triple DES cipher instead of PRESENT.

package main

import (
	"fmt"
	"log"

	"github.com/yi-jiayu/presents"
)

func main() {
	// 24-byte triple DES key
	key := make([]byte, 24)
	p, err := presents.NewTripleDES(key, nil)
	if err != nil {
		log.Fatal(err)
	}

	s := p.Wrap(1213486160)
	fmt.Println(s)

	n, err := p.Unwrap(s)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(n)
}
Output:

Yq4drxXQtcJ
1213486160

func NewWithCipher

func NewWithCipher(c cipher.Block, options *Options) (*Presents, error)

NewWithCipher returns a new Presents instance from the provided cipher.Block and options. The provided cipher.Block should have a 64-bit block size.

Example

You can also provide your own cipher.Block implementation as long as it has a 64-bit block size. This example shows how you can use the Blowfish cipher provided by the golang.org/x/crypto/blowfish package.

package main

import (
	"fmt"
	"log"

	"github.com/yi-jiayu/presents"
	"golang.org/x/crypto/blowfish"
)

func main() {
	// 56-byte Blowfish key
	key := make([]byte, 56)
	c, err := blowfish.NewCipher(key)
	if err != nil {
		log.Fatal(err)
	}
	p, err := presents.NewWithCipher(c, nil)
	if err != nil {
		log.Fatal(err)
	}

	s := p.Wrap(1213486160)
	fmt.Println(s)

	n, err := p.Unwrap(s)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(n)
}
Output:

woSdQdAYuiK
1213486160

func (*Presents) Unwrap

func (p *Presents) Unwrap(s string) (uint64, error)

Unwrap converts a string back to an unsigned 64-bit integer. It returns an error if the string cannot be converted using the given alphabet.

func (*Presents) Wrap

func (p *Presents) Wrap(n uint64) string

Wrap converts an unsigned 64-bit integer to a string.

Jump to

Keyboard shortcuts

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