github.com/cloudflare/circl@v1.5.0/abe/cpabe/tkn20/example_test.go (about)

     1  package tkn20_test
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"fmt"
     7  	"log"
     8  	"strconv"
     9  
    10  	cpabe "github.com/cloudflare/circl/abe/cpabe/tkn20"
    11  )
    12  
    13  func checkPolicy(in map[string][]string) bool {
    14  	possiblePairs := map[string][]string{
    15  		"occupation": {"wizard", "doctor", "ghost"},
    16  		"country":    {"US", "croatia"},
    17  		"age":        {},
    18  	}
    19  	isValid := func(key string, value string) bool {
    20  		vs, ok := possiblePairs[key]
    21  		if !ok {
    22  			return false
    23  		}
    24  		if key == "age" {
    25  			age, err := strconv.Atoi(value)
    26  			if err != nil {
    27  				return false
    28  			}
    29  			if age < 13 || age > 100 {
    30  				return false
    31  			}
    32  		} else {
    33  			for _, v := range vs {
    34  				if value == v {
    35  					return true
    36  				}
    37  			}
    38  		}
    39  		return false
    40  	}
    41  	for k, v := range in {
    42  		for _, value := range v {
    43  			if !isValid(k, value) {
    44  				return false
    45  			}
    46  		}
    47  	}
    48  	return true
    49  }
    50  
    51  func Example() {
    52  	policyStr := `(occupation: doctor) and (country: US)`
    53  	invalidPolicyStr := `(title: doctor) and (country: pacific)`
    54  	msgStr := `must have the precious 🎃`
    55  	wrongAttrsMap := map[string]string{"occupation": "doctor", "country": "croatia"}
    56  	rightAttrsMap := map[string]string{"occupation": "doctor", "country": "US", "age": "16"}
    57  
    58  	publicKey, systemSecretKey, err := cpabe.Setup(rand.Reader)
    59  	if err != nil {
    60  		log.Fatalf("%s", err)
    61  	}
    62  
    63  	policy := cpabe.Policy{}
    64  	err = policy.FromString(policyStr)
    65  	if err != nil {
    66  		log.Fatal(err)
    67  	}
    68  	if !checkPolicy(policy.ExtractAttributeValuePairs()) {
    69  		log.Fatalf("policy check failed for valid policy")
    70  	}
    71  
    72  	fmt.Println(policy.String())
    73  	invalidPolicy := cpabe.Policy{}
    74  	err = invalidPolicy.FromString(invalidPolicyStr)
    75  	if err != nil {
    76  		log.Fatal(err)
    77  	}
    78  	if checkPolicy(invalidPolicy.ExtractAttributeValuePairs()) {
    79  		log.Fatalf("policy check should fail for invalid policy")
    80  	}
    81  
    82  	// encrypt the secret message for a given policy
    83  	ct, err := publicKey.Encrypt(rand.Reader, policy, []byte(msgStr))
    84  	if err != nil {
    85  		log.Fatalf("%s", err)
    86  	}
    87  	fmt.Printf("plaintext size: %v bytes\n", len(msgStr))
    88  	fmt.Printf("ciphertext size: %v bytes\n", len(ct))
    89  
    90  	// generate secret key for certain set of attributes
    91  	wrongAttrs := cpabe.Attributes{}
    92  	wrongAttrs.FromMap(wrongAttrsMap)
    93  	rightAttrs := cpabe.Attributes{}
    94  	rightAttrs.FromMap(rightAttrsMap)
    95  
    96  	wrongSecretKey, _ := systemSecretKey.KeyGen(rand.Reader, wrongAttrs)
    97  	rightSecretKey, _ := systemSecretKey.KeyGen(rand.Reader, rightAttrs)
    98  
    99  	wrongSat := policy.Satisfaction(wrongAttrs)
   100  	if wrongSat {
   101  		log.Fatalf("wrong attributes should not satisfy policy")
   102  	}
   103  	rightSat := policy.Satisfaction(rightAttrs)
   104  	if !rightSat {
   105  		log.Fatalf("right attributes should satisfy policy")
   106  	}
   107  
   108  	// wrong attrs should not satisfy ciphertext
   109  	wrongCtSat := wrongAttrs.CouldDecrypt(ct)
   110  	if wrongCtSat {
   111  		log.Fatalf("wrong attrs should not satisfy ciphertext")
   112  	}
   113  	rightCtSat := rightAttrs.CouldDecrypt(ct)
   114  	if rightCtSat == false {
   115  		log.Fatalf("right attrs should satisfy ciphertext")
   116  	}
   117  
   118  	// attempt to decrypt with wrong attributes should fail
   119  	pt, err := wrongSecretKey.Decrypt(ct)
   120  	if err == nil {
   121  		log.Fatalf("decryption using wrong attrs should have failed, plaintext: %s", pt)
   122  	}
   123  
   124  	pt, err = rightSecretKey.Decrypt(ct)
   125  	if err != nil {
   126  		log.Fatalf("decryption using right attrs should have succeeded, plaintext: %s", pt)
   127  	}
   128  	if !bytes.Equal(pt, []byte(msgStr)) {
   129  		log.Fatalf("recovered plaintext: %s is not equal to original msg: %s", pt, msgStr)
   130  	}
   131  	fmt.Println("Successfully recovered plaintext")
   132  	// Output:
   133  	// (occupation:doctor and country:US)
   134  	// plaintext size: 27 bytes
   135  	// ciphertext size: 2747 bytes
   136  	// Successfully recovered plaintext
   137  }