sphinxmixcrypto

package module
v0.0.0-...-818c312 Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2017 License: MIT Imports: 9 Imported by: 0

README

======================================
sphinx mixnet packet crypto for golang
======================================

.. image:: https://travis-ci.org/applied-mixnetworks/go-sphinxmixcrypto.png?branch=master
    :target: https://www.travis-ci.org/applied-mixnetworks/go-sphinxmixcrypto
    :alt: travis for go-sphinxmixcrypto

.. image:: https://coveralls.io/repos/github/applied-mixnetworks/go-sphinxmixcrypto/badge.svg?branch=master
  :target: https://coveralls.io/github/applied-mixnetworks/go-sphinxmixcrypto
  :alt: coveralls for go-sphinxmixcrypto

.. image:: https://godoc.org/github.com/applied-mixnetworks/go-sphinxmixcrypto?status.svg
  :target: https://godoc.org/github.com/applied-mixnetowrks/go-sphinxmixcrypto
  :alt: golang api docs for go-sphinxmixcrypto


Warning
=======
This code has not been formally audited by a cryptographer. It therefore should not
be considered safe or correct. Use it at your own risk! (however test vectors are verified using
other language implementations: rust, golang, python trinity!)


details
-------

Read the Sphinx paper:

**Sphinx: A Compact and Provably Secure Mix Format**
by George Danezis and Ian Goldberg

- http://www0.cs.ucl.ac.uk/staff/G.Danezis/papers/sphinx-eprint.pdf


status
------

This package is binary compatible with the python library:

- https://github.com/david415/sphinxmixcrypto

The two libraries share unit test vectors to prove that they are binary compatible.


dependencies
------------

You can see a list of dependencies on godocs:

- https://godoc.org/github.com/david415/go-sphinxmixcrypto?imports

Currently this library depends on my own LIONESS wide block cipher implementation:

- https://github.com/david415/go-lioness

The other external dependencies include:

- https://git.schwanenlied.me/yawning/chacha20
- https://github.com/minio/blake2b-simd
- https://golang.org/x/crypto/curve25519


=======
license
=======

go-sphinxmixcrypto is free software made available via the MIT License.
License details located in the LICENSE file.

Some code was inspired or copied from Lightning-Onion's partial Sphinx
implementation located here:

- https://github.com/lightningnetwork/lightning-onion/blob/master/sphinx.go
- https://github.com/lightningnetwork/lightning-onion/blob/master/sphinx_test.go

Included in this repo is Lightning-Onion's MIT License file:
LICENSE-lightening-onion


=======
contact
=======

* email dstainton415@gmail.com
* gpg key ID 0x836501BE9F27A723
* gpg fingerprint F473 51BD 87AB 7FCF 6F88  80C9 8365 01BE 9F27 A723

Documentation

Overview

Package sphinxmixcrypto provides cryptographic encoding/decoding using the Sphinx mix network packet format as described in the paper

"Sphinx: A Compact and Provably Secure Mix Format" written by Ian Goldberg and George Danezis

If you're looking to dive right into code, see the unit tests for examples.

Index

Constants

View Source
const (
	// ExitNode indicates an exit hop
	ExitNode = 0
	// MoreHops indicates another mix hop
	MoreHops = 255
	// ClientHop indicates a client hop
	ClientHop = 128
	// Failure indicates a prefix-free decoding failure
	Failure
)

Variables

View Source
var (
	// ErrInvalidBlockSize indicates block size <= 0
	ErrInvalidBlockSize = errors.New("invalid block size")
	// ErrInvalidData indicates zero size data
	ErrInvalidData = errors.New("invalid data, empty")
	// ErrInvalidPadding indicates an invalid padded input
	ErrInvalidPadding = errors.New("invalid padding on input")
	// ErrInvalidPadOffset indicates a bad padding offset
	ErrInvalidPadOffset = errors.New("invalid padding offset")
	// ErrInputTooBig indicates the input data is too big
	ErrInputTooBig = errors.New("input too big")
)
View Source
var (
	// ErrReplayedPacket indicates a replay attack
	ErrReplayedPacket = fmt.Errorf("sphinx packet replay error")
)
View Source
var (
	// ErrorPKIKeyNotFound indicates an identity was not found
	ErrorPKIKeyNotFound = fmt.Errorf("Sphinx PKI identity not found")
)

Functions

func AddPadding

func AddPadding(src []byte, blockSize int) ([]byte, error)

AddPadding returns src with padding appended

func ComposeReplyBlock

func ComposeReplyBlock(messageID [16]byte, params *SphinxParams, route [][16]byte, pki SphinxPKI, destination [16]byte, randReader io.Reader) (*ReplyBlockDecryptionToken, *ReplyBlock, error)

ComposeReplyBlock produces a reply block and the corresponding decryption token

func EncodeDestination

func EncodeDestination(destination []byte) []byte

EncodeDestination encodes a destination using our prefix-free encoding

func PrefixFreeDecode

func PrefixFreeDecode(s []byte) (int, []byte, []byte)

PrefixFreeDecode decodes the prefix-free encoding. Return the type, value, and the remainder of the input string

func RemovePadding

func RemovePadding(src []byte) ([]byte, error)

RemovePadding returns src with padding removed

Types

type Blake2bDigest

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

Blake2bDigest implements our Digest interface

func NewBlake2bDigest

func NewBlake2bDigest() *Blake2bDigest

NewBlake2bDigest returns a blake2b digest

func (*Blake2bDigest) DeriveHMACKey

func (b *Blake2bDigest) DeriveHMACKey(secret [32]byte) ([16]byte, error)

DeriveHMACKey derives a key to be used with an HMAC

func (*Blake2bDigest) DeriveStreamCipherKey

func (b *Blake2bDigest) DeriveStreamCipherKey(secret [32]byte) [32]byte

DeriveStreamCipherKey derives a key to be used with a stream cipher

func (*Blake2bDigest) HMAC

func (b *Blake2bDigest) HMAC(key [securityParameter]byte, data []byte) ([securityParameter]byte, error)

HMAC computes a HMAC

func (*Blake2bDigest) Hash

func (b *Blake2bDigest) Hash(data []byte) [32]byte

Hash returns a 32 byte hash of the data

func (*Blake2bDigest) HashBlindingFactor

func (b *Blake2bDigest) HashBlindingFactor(alpha [32]byte, secret [32]byte) [32]byte

HashBlindingFactor is used to hash the blinding factory

func (*Blake2bDigest) HashReplay

func (b *Blake2bDigest) HashReplay(secret [32]byte) [32]byte

HashReplay produces a hash of the hop key for catching replay attacks

type BlockCipher

type BlockCipher interface {
	Decrypt(key [lioness.KeyLen]byte, block []byte) ([]byte, error)
	Encrypt(key [lioness.KeyLen]byte, block []byte) ([]byte, error)
	CreateBlockCipherKey(secret [32]byte) ([lioness.KeyLen]byte, error)
}

BlockCipher is an interface for our Lioness block cipher

type Chacha20Stream

type Chacha20Stream struct{}

Chacha20Stream the StreamCipher interface

func (*Chacha20Stream) GenerateStream

func (s *Chacha20Stream) GenerateStream(key [chachaKeyLen]byte, n uint) ([]byte, error)

GenerateStream generates a stream of n bytes given a key

type Digest

type Digest interface {
	HMAC(key [securityParameter]byte, data []byte) ([securityParameter]byte, error)
	Hash(data []byte) [32]byte
	DeriveHMACKey(secret [32]byte) ([16]byte, error)
	DeriveStreamCipherKey(secret [32]byte) [32]byte
	HashReplay(secret [32]byte) [32]byte
	HashBlindingFactor(alpha [32]byte, secret [32]byte) [32]byte
}

Digest is an interface for our use of Blake2b as a hash and hmac

type GroupCurve25519

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

GroupCurve25519 performs group operations on the curve

func NewGroupCurve25519

func NewGroupCurve25519() *GroupCurve25519

NewGroupCurve25519 creates a new GroupCurve25519

func (*GroupCurve25519) ExpOn

func (g *GroupCurve25519) ExpOn(base, exp [32]byte) [32]byte

ExpOn does scalar multiplication on the curve

func (*GroupCurve25519) GenerateSecret

func (g *GroupCurve25519) GenerateSecret(rand io.Reader) ([32]byte, error)

GenerateSecret generats a new key

func (*GroupCurve25519) MakeExp

func (g *GroupCurve25519) MakeExp(data [32]byte) [32]byte

MakeExp flips some bits

func (*GroupCurve25519) MultiExpOn

func (g *GroupCurve25519) MultiExpOn(base [32]byte, exps [][32]byte) [32]byte

MultiExpOn does multiple scalar multiplication operations and returns the accumulator

type LionessBlockCipher

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

LionessBlockCipher implements the BlockCipher interface.

func NewLionessBlockCipher

func NewLionessBlockCipher() *LionessBlockCipher

NewLionessBlockCipher creates a lioness block cipher

func (*LionessBlockCipher) CreateBlockCipherKey

func (l *LionessBlockCipher) CreateBlockCipherKey(secret [32]byte) ([lioness.KeyLen]byte, error)

CreateBlockCipherKey returns the Lioness block cipher key

func (*LionessBlockCipher) Decrypt

func (l *LionessBlockCipher) Decrypt(key [lioness.KeyLen]byte, block []byte) ([]byte, error)

Decrypt decrypts a block of data with the given key.

func (*LionessBlockCipher) Encrypt

func (l *LionessBlockCipher) Encrypt(key [lioness.KeyLen]byte, block []byte) ([]byte, error)

Encrypt encrypts a block of data with the given key.

type MixHeader

type MixHeader struct {
	Version      byte
	EphemeralKey [32]byte                // alpha
	RoutingInfo  []byte                  // beta
	HeaderMAC    [securityParameter]byte // gamma
}

MixHeader contains the sphinx header but not the payload. A version number is also included; TODO: make the version number do something useful.

type MixHeaderFactory

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

MixHeaderFactory builds mix headers

func NewMixHeaderFactory

func NewMixHeaderFactory(params *SphinxParams, pki SphinxPKI, randReader io.Reader) *MixHeaderFactory

NewMixHeaderFactory creates a new mix header factory

func (*MixHeaderFactory) BuildHeader

func (f *MixHeaderFactory) BuildHeader(route [][16]byte, destination []byte, messageID [16]byte) (*MixHeader, [][32]byte, error)

BuildHeader generates a mix header containing the neccessary onion routing information required to propagate the message through the mixnet. If the computation is successful then a *MixHeader is returned along with a slice of 32byte shared secrets for each mix hop.

type PrivateKey

type PrivateKey interface {
	// GetPrivateKey returns the private key
	GetPrivateKey() [32]byte
}

PrivateKey interface is used to access the private key so the mix can unwrap packets

type ReplayCache

type ReplayCache interface {
	// Get returns true if the hash value is present in the map
	Get([32]byte) bool
	// Set sets a hash value in the map
	Set([32]byte)
	// Flush flushes the map
	Flush()
}

ReplayCache is an interface for detecting packet replays

type ReplyBlock

type ReplyBlock struct {
	// Header is a mix header
	Header *MixHeader
	// Key is the symmetric encryption key
	Key [32]byte
	// FirstHop represent the first hop
	FirstHop [16]byte
}

ReplyBlock is a struct that represents a single use reply block

func (*ReplyBlock) ComposeForwardMessage

func (r *ReplyBlock) ComposeForwardMessage(params *SphinxParams, message []byte) ([]byte, *SphinxPacket, error)

ComposeForwardMessage produces a sphinx packet from the reply block and a message

type ReplyBlockDecryptionToken

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

ReplyBlockDecryptionToken represents a decryption token that can be used to decrypt a ciphertext blob produce and delivered by a ReplyBlock

func (*ReplyBlockDecryptionToken) Decrypt

func (c *ReplyBlockDecryptionToken) Decrypt(payload []byte) ([]byte, error)

Decrypt decrypts a ciphertext blob produced by a ReplyBlock

type SphinxPKI

type SphinxPKI interface {
	Get([16]byte) ([32]byte, error)
	Identities() [][16]byte
}

SphinxPKI is an interface specifying the Sphinx PKI.

type SphinxPacket

type SphinxPacket struct {
	Header  *MixHeader
	Payload []byte // delta
}

SphinxPacket represents a forwarding message containing onion wrapped hop-to-hop routing information along with an onion encrypted payload message addressed to the final destination.

func NewOnionReply

func NewOnionReply(header *MixHeader, payload []byte) *SphinxPacket

NewOnionReply is used to create an SphinxPacket with a specified header and payload. This is used by the WrapReply to create Single Use Reply Blocks

type SphinxPacketFactory

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

SphinxPacketFactory builds onion packets

func NewSphinxPacketFactory

func NewSphinxPacketFactory(params *SphinxParams, pki SphinxPKI, randReader io.Reader) *SphinxPacketFactory

NewSphinxPacketFactory creates a new onion packet factory

func (*SphinxPacketFactory) BuildForwardSphinxPacket

func (f *SphinxPacketFactory) BuildForwardSphinxPacket(route [][16]byte, destination [16]byte, payload []byte) (*SphinxPacket, error)

BuildForwardSphinxPacket builds a forward oniion packet

type SphinxParams

type SphinxParams struct {
	// PayloadSize is the packet payload size
	PayloadSize int
	// NumMaxHops is the maximum path length.
	MaxHops int
}

SphinxParams are the mixnet parameters

type StreamCipher

type StreamCipher interface {
	GenerateStream(key [chachaKeyLen]byte, n uint) ([]byte, error)
}

StreamCipher is an interface for our chacha20 stream generator

type UnwrappedMessage

type UnwrappedMessage struct {
	ProcessAction int
	Alpha         []byte // ephemeral key
	Beta          []byte // routing information
	Gamma         []byte // MAC
	Delta         []byte // message body
	NextHop       []byte
	ClientID      []byte
	MessageID     []byte
}

UnwrappedMessage is produced by SphinxNode's Unwrap method

func SphinxPacketUnwrap

func SphinxPacketUnwrap(params *SphinxParams, replayCache ReplayCache, privateKey PrivateKey, packet *SphinxPacket) (*UnwrappedMessage, error)

SphinxPacketUnwrap performs the decryption operation that a mix would perform An error is returned if the MAC doesn't match or if a packet is replayed.

Jump to

Keyboard shortcuts

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