redactionschemes

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Feb 23, 2022 License: GPL-3.0 Imports: 23 Imported by: 0

README

Golang Library for Redactable Signatures

⚠️WARNING⚠️ THIS LIBRARY HAS NOT BEEN VERIFIED AT ALL AND IS PROBABLY NOT SAFE TO USE!!!

This library includes 3 verifiable redaction schemes:

Currently, all schemes use SHA256 for hashing, and the Merkle and Naive scheme use ECDSA for signing.

For examples, look at the tests.

Partitioning

To keep the signatures small and the sign/verify/redact operations efficient, the input data is stored in partitions of data. We provide a helper struct PartitionedData with many helper functions to handle this.

TODO

  • Make hash function modular
  • Make used base signature scheme modular for naive and merkle
  • Probably replace PartitionedData with something more sensible?
  • Merkle tree-based scheme
    • Bitstrings very weird way to save nodes position
    • Implement support for redacting redacted signatures
  • RSA:
    • Make used prime bits configurable
    • Is this way to generate the coprimes even sane and safe?

Short Description of Each Scheme

Naive Scheme

NaiveSignature simply uses the underlying ECDSA key to sign each partition individually. To prohibit the reuse of each partition (reordering attack), we append an ID on each hash, as well as its position. We hard coded the hash of the data as ID. For a message m of length n, the signature is:

Sig(H(n || ID)) || Sig(H(ID || 0 || m_0)) || ... || Sig(H(ID || n || m_n))

Merkle Tree-based Scheme

JohnsonMerkleSignature is based on Johnson et al. and uses a Merkle tree-based structure to sign the data. The signature benefits from consecutive redactions, as neighboring redacted nodes in the Merkle tree will be merged. Thus the signature is largest, if the redaction is sparse.

RSA-based Scheme

JohnsonRSASignature is based on Johnson et al. and uses the RSA accumulator technique to achieve a constant sized signature. This currently use a hash function which maps to the primes, I don't know if this is safe or even sane... Due to the repeated exponentiations, this scheme can get really slow!

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Base64ImageToByteArray

func Base64ImageToByteArray(image_base64encoded string) ([]byte, error)

Base64ImageToByteArray converts a base64-encoded image and converts it to a byte array.

func CommaSeperatedIndicesArray

func CommaSeperatedIndicesArray(s string) ([]int, error)

CommaSeperatedIndicesArray takes a comma seperated string of indices and converts it into a slice of indices.

func G

func G(InputBytes []byte) []byte

Length-doubling pseudorandom generator

func H

func H(InputBytes []byte) []byte

H defines the base cryptographic hash function, which is currently just SHA256. FIXME: Make this configurable?

Types

type JohnsonMerkleSignature

type JohnsonMerkleSignature struct {
	BaseSignature []byte
	PublicKey     ecdsa.PublicKey
	Key           []byte                      // This is only visible before the redaction
	RedactedKeys  map[string]redactedProperty // And this afterwards, these are the conodes keys
	RedactedHash  map[string]redactedProperty // and these the hashes of the parents of the redacted nodes
}

func (*JohnsonMerkleSignature) Marshal

func (sig *JohnsonMerkleSignature) Marshal() (string, error)

func (*JohnsonMerkleSignature) Redact

func (orig_signature *JohnsonMerkleSignature) Redact(redacted_indices []int, data *PartitionedData) (RedactableSignature, error)

Redacts an existing signature based on data. When redacting, k_epsilon is not publicsed, as with it we could just calculate all the hashes and possibly get access to the redacted data by bruteforcing or similar. Instead, we just publicise the co-nodes keys, as well as the parent node of the redacted leaf

func (*JohnsonMerkleSignature) Sign added in v0.2.0

func (sig *JohnsonMerkleSignature) Sign(data *PartitionedData, private_key *crypto.PrivateKey) error

Sign uses the private_key to sign data redactably.

func (*JohnsonMerkleSignature) Unmarshal added in v0.2.0

func (sig *JohnsonMerkleSignature) Unmarshal(input string) error

func (*JohnsonMerkleSignature) Verify

func (sig *JohnsonMerkleSignature) Verify(data *PartitionedData) error

Verifies if a given signature matches the supplied data This rebuilds the tree by regenerating the co-node-trees, as well as using the supplied hashes to retrieve the root node hash

type JohnsonRSASignature

type JohnsonRSASignature struct {
	DocumentKey   []byte
	BaseSignature big.Int
	Generator     big.Int
	PublicKey     rsa.PublicKey
}

func (*JohnsonRSASignature) Marshal

func (sig *JohnsonRSASignature) Marshal() (string, error)

func (*JohnsonRSASignature) Redact

func (sig *JohnsonRSASignature) Redact(redacted_indices []int, data *PartitionedData) (RedactableSignature, error)

Redacts an existing signature by mutliplying it with the removed hashes

func (*JohnsonRSASignature) Sign added in v0.2.0

func (sig *JohnsonRSASignature) Sign(data *PartitionedData, private_key *crypto.PrivateKey) error

Signs the input data according to the paper

func (*JohnsonRSASignature) Unmarshal added in v0.2.0

func (sig *JohnsonRSASignature) Unmarshal(input string) error

func (*JohnsonRSASignature) Verify

func (sig *JohnsonRSASignature) Verify(data *PartitionedData) error

Verifies a signature according to the paper

type NaiveSignature

type NaiveSignature struct {
	Identifier    []byte
	Length        int
	BaseSignature []byte
	Signatures    [][]byte
	PublicKey     ecdsa.PublicKey
}

func (*NaiveSignature) Marshal

func (sig *NaiveSignature) Marshal() (string, error)

func (*NaiveSignature) Redact added in v0.2.0

func (sig *NaiveSignature) Redact(redacted_indices []int, data *PartitionedData) (RedactableSignature, error)

func (*NaiveSignature) Sign added in v0.2.0

func (sig *NaiveSignature) Sign(data *PartitionedData, private_key *crypto.PrivateKey) error

func (*NaiveSignature) Unmarshal added in v0.2.0

func (sig *NaiveSignature) Unmarshal(sig_string string) error

func (*NaiveSignature) Verify

func (sig *NaiveSignature) Verify(data *PartitionedData) error

type PartitionedData

type PartitionedData [][]byte

PartitionedData is a wrapper for the input data to sign. Depending on the structure of the data at hand, you might want to choose a different partition: E.g. a partition for each field of a formular, or each word in a text. Depending on the signature scheme you use, the amount of partitions can have an impact on the size and performance.

func ImageToPartitionedData

func ImageToPartitionedData(img image.Image, chunksX int, chunksY int) (*PartitionedData, error)

ImagetoPartitionedData converts a html-base64 encoded image into a chunk array with chunksX * chunksY resolution.

func StringToPartitionedData

func StringToPartitionedData(s string) *PartitionedData

StringToPartitionedData partitions a string s word-wise

func UnmarshalPartitionedData

func UnmarshalPartitionedData(s string) (*PartitionedData, error)

UnmarshalPartitionedData unmarshales a JSON/base64 encoded representation of the partitioned data.

func (PartitionedData) GetRedactedIndicesArray

func (c PartitionedData) GetRedactedIndicesArray() []int

GetRedactedIndicesArray returns all indices of partitions where the bytecount is zero.

func (PartitionedData) Hash

func (c PartitionedData) Hash() []byte

Hash returns the SHA256 of the whole partitioned data.

func (PartitionedData) Marshal

func (c PartitionedData) Marshal() (string, error)

Marshal creates a JSON/base64 encoded representation of the partitioned data.

func (PartitionedData) Redact

func (c PartitionedData) Redact(redacted_indices []int) (*PartitionedData, error)

Redact creates a copy of the data where the indices in redacted_indices are redacted.

func (PartitionedData) ToByteArray

func (c PartitionedData) ToByteArray() []byte

ToByteArray returns a one-dimensional slice of all partitions.

func (PartitionedData) ToDataURL

func (c PartitionedData) ToDataURL(chunksX int, chunksY int) (string, error)

ToDataURL converts the PartitionedData c with chunksX*chunksY image partitions into a whole base64-encoded data url.

func (PartitionedData) ToDataURLs

func (c PartitionedData) ToDataURLs() []string

ToDataURLs will decode each partition as an data uri.

func (PartitionedData) ToImage

func (c PartitionedData) ToImage(chunksX int, chunksY int) (image.Image, error)

ToImage converts the PartitionedData c with chunksX*chunksY image partitions into a whole image.

type RedactableSignature added in v0.2.0

type RedactableSignature interface {
	Sign(data *PartitionedData, private_key *crypto.PrivateKey) error
	Redact(redacted_indices []int, data *PartitionedData) (RedactableSignature, error)
	Verify(data *PartitionedData) error
	Marshal() (string, error)
	Unmarshal(input string) error
}

RedactableSignature provides the interface for redactable signatures.

Sign creates the initial signature for data using the private_key. Note, that not all schemes accept any type of private key.

Redact creates a new signature, where the indices noted in redacted_indices are redacted. Note, that data of corse needs to contain the data which is beeing redacted. Note, that the new signature does not necessarily need to be new: e.g. with NaiveSignature, a redaction does not change the signature.

Jump to

Keyboard shortcuts

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