tkn20

package
v1.3.9 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2024 License: BSD-3-Clause Imports: 4 Imported by: 0

Documentation

Overview

Package tkn20 implements a ciphertext-policy ABE by Tomida, Kawahara, Nishimaki.

This is an implementation of an IND-CCA2 secure variant of the Ciphertext-Policy Attribute Based Encryption (CP-ABE) scheme by J. Tomida, Y. Kawahara, and R. Nishimaki. Fast, compact, and expressive attribute-based encryption. In A. Kiayias, M. Kohlweiss, P. Wallden, and V. Zikas, editors, PKC, volume 12110 of Lecture Notes in Computer Science, pages 3–33. Springer, 2020. https://eprint.iacr.org/2019/966

Update v1.3.8

As of v1.3.8, ciphertext format changed to use wider prefixes. Ciphertexts in the previous format are still decryptable. The following functions are backwards-compatible:

Example
package main

import (
	"bytes"
	"crypto/rand"
	"fmt"
	"log"
	"strconv"

	cpabe "github.com/cloudflare/circl/abe/cpabe/tkn20"
)

func checkPolicy(in map[string][]string) bool {
	possiblePairs := map[string][]string{
		"occupation": {"wizard", "doctor", "ghost"},
		"country":    {"US", "croatia"},
		"age":        {},
	}
	isValid := func(key string, value string) bool {
		vs, ok := possiblePairs[key]
		if !ok {
			return false
		}
		if key == "age" {
			age, err := strconv.Atoi(value)
			if err != nil {
				return false
			}
			if age < 13 || age > 100 {
				return false
			}
		} else {
			for _, v := range vs {
				if value == v {
					return true
				}
			}
		}
		return false
	}
	for k, v := range in {
		for _, value := range v {
			if !isValid(k, value) {
				return false
			}
		}
	}
	return true
}

func main() {
	policyStr := `(occupation: doctor) and (country: US)`
	invalidPolicyStr := `(title: doctor) and (country: pacific)`
	msgStr := `must have the precious 🎃`
	wrongAttrsMap := map[string]string{"occupation": "doctor", "country": "croatia"}
	rightAttrsMap := map[string]string{"occupation": "doctor", "country": "US", "age": "16"}

	publicKey, systemSecretKey, err := cpabe.Setup(rand.Reader)
	if err != nil {
		log.Fatalf("%s", err)
	}

	policy := cpabe.Policy{}
	err = policy.FromString(policyStr)
	if err != nil {
		log.Fatal(err)
	}
	if !checkPolicy(policy.ExtractAttributeValuePairs()) {
		log.Fatalf("policy check failed for valid policy")
	}

	fmt.Println(policy.String())
	invalidPolicy := cpabe.Policy{}
	err = invalidPolicy.FromString(invalidPolicyStr)
	if err != nil {
		log.Fatal(err)
	}
	if checkPolicy(invalidPolicy.ExtractAttributeValuePairs()) {
		log.Fatalf("policy check should fail for invalid policy")
	}

	// encrypt the secret message for a given policy
	ct, err := publicKey.Encrypt(rand.Reader, policy, []byte(msgStr))
	if err != nil {
		log.Fatalf("%s", err)
	}
	fmt.Printf("plaintext size: %v bytes\n", len(msgStr))
	fmt.Printf("ciphertext size: %v bytes\n", len(ct))

	// generate secret key for certain set of attributes
	wrongAttrs := cpabe.Attributes{}
	wrongAttrs.FromMap(wrongAttrsMap)
	rightAttrs := cpabe.Attributes{}
	rightAttrs.FromMap(rightAttrsMap)

	wrongSecretKey, _ := systemSecretKey.KeyGen(rand.Reader, wrongAttrs)
	rightSecretKey, _ := systemSecretKey.KeyGen(rand.Reader, rightAttrs)

	wrongSat := policy.Satisfaction(wrongAttrs)
	if wrongSat {
		log.Fatalf("wrong attributes should not satisfy policy")
	}
	rightSat := policy.Satisfaction(rightAttrs)
	if !rightSat {
		log.Fatalf("right attributes should satisfy policy")
	}

	// wrong attrs should not satisfy ciphertext
	wrongCtSat := wrongAttrs.CouldDecrypt(ct)
	if wrongCtSat {
		log.Fatalf("wrong attrs should not satisfy ciphertext")
	}
	rightCtSat := rightAttrs.CouldDecrypt(ct)
	if rightCtSat == false {
		log.Fatalf("right attrs should satisfy ciphertext")
	}

	// attempt to decrypt with wrong attributes should fail
	pt, err := wrongSecretKey.Decrypt(ct)
	if err == nil {
		log.Fatalf("decryption using wrong attrs should have failed, plaintext: %s", pt)
	}

	pt, err = rightSecretKey.Decrypt(ct)
	if err != nil {
		log.Fatalf("decryption using right attrs should have succeeded, plaintext: %s", pt)
	}
	if !bytes.Equal(pt, []byte(msgStr)) {
		log.Fatalf("recovered plaintext: %s is not equal to original msg: %s", pt, msgStr)
	}
	fmt.Println("Successfully recovered plaintext")
}
Output:

(occupation:doctor and country:US)
plaintext size: 27 bytes
ciphertext size: 2747 bytes
Successfully recovered plaintext

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Setup

func Setup(rand io.Reader) (PublicKey, SystemSecretKey, error)

Types

type AttributeKey

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

func (*AttributeKey) Decrypt

func (s *AttributeKey) Decrypt(ct []byte) ([]byte, error)

func (*AttributeKey) Equal

func (s *AttributeKey) Equal(s2 *AttributeKey) bool

func (*AttributeKey) MarshalBinary

func (s *AttributeKey) MarshalBinary() ([]byte, error)

func (*AttributeKey) UnmarshalBinary

func (s *AttributeKey) UnmarshalBinary(data []byte) error

type Attributes

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

func (*Attributes) CouldDecrypt

func (a *Attributes) CouldDecrypt(ciphertext []byte) bool

func (*Attributes) Equal

func (a *Attributes) Equal(a2 *Attributes) bool

func (*Attributes) FromMap

func (a *Attributes) FromMap(in map[string]string)

type Policy

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

func (*Policy) Equal

func (p *Policy) Equal(p2 *Policy) bool

func (*Policy) ExtractAttributeValuePairs

func (p *Policy) ExtractAttributeValuePairs() map[string][]string

func (*Policy) ExtractFromCiphertext

func (p *Policy) ExtractFromCiphertext(ct []byte) error

func (*Policy) FromString

func (p *Policy) FromString(str string) error

func (*Policy) Satisfaction

func (p *Policy) Satisfaction(a Attributes) bool

func (*Policy) String

func (p *Policy) String() string

type PublicKey

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

func (*PublicKey) Encrypt

func (p *PublicKey) Encrypt(rand io.Reader, policy Policy, msg []byte) ([]byte, error)

func (*PublicKey) Equal

func (p *PublicKey) Equal(p2 *PublicKey) bool

func (*PublicKey) MarshalBinary

func (p *PublicKey) MarshalBinary() ([]byte, error)

func (*PublicKey) UnmarshalBinary

func (p *PublicKey) UnmarshalBinary(data []byte) error

type SystemSecretKey

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

func (*SystemSecretKey) Equal

func (msk *SystemSecretKey) Equal(msk2 *SystemSecretKey) bool

func (*SystemSecretKey) KeyGen

func (msk *SystemSecretKey) KeyGen(rand io.Reader, attrs Attributes) (AttributeKey, error)

func (*SystemSecretKey) MarshalBinary

func (msk *SystemSecretKey) MarshalBinary() ([]byte, error)

func (*SystemSecretKey) UnmarshalBinary

func (msk *SystemSecretKey) UnmarshalBinary(data []byte) error

Directories

Path Synopsis
internal
dsl
tkn

Jump to

Keyboard shortcuts

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