项目作者: marcellop71

项目描述 :
multi-authority attribute based encryption
高级语言: Go
项目地址: git://github.com/marcellop71/mosaic.git
创建时间: 2020-04-30T16:34:18Z
项目社区:https://github.com/marcellop71/mosaic

开源协议:GNU Affero General Public License v3.0

下载


Mosaic

Mosaic is a library doing Attribute Based Encryption (ABE). It is meant to be used as a example of a cryptographic core to be embedded in any solution willing to rely on an ABE scheme of this kind
(a Multi-Authority CipherText-Policy scheme, see below).

Please remark

The code is for demonstration purposes only and it is not suitable
for embedding in any reliable cryptographic solutions.
A quantity of structure which should be needed in any reliable cryptographic solution is missing in the code base
(about randomness, hashing functions used, selection of curves and pairings and underlying cryptographic library, hash-to-groups primitives,
secure communication, in-memory management of cryptographic calculations and many other issues).
Moreover, the code is not fully tested (nor formally verified),
nor yet implementing any reliable error management procedure and
should not be used in production environments.

The library is under the copyleft license AGPL-3.0.

library is under development (APIs are subject to change) please check for updates

Attribute Based Encryption

Attribute based encryption is about sharing a secret according to attributes and policies.
A policy is an expression (boolean or integer-valued with linear constraints)
whose variables are called attributes.
The cryptographic scheme allows the encryption of a secret
according to a given policy, splitting the secret among the attributes mentioned in the policy.
The secret could be recovered only by a set of keys corresponding to attributes
which satisfy the policy (i.e., make the policy expression evaluate to true).

Those keys are attached to attributes and users (both strings or, in general, hashable objects).
Users can obtain these attribute-keys asking some authority for them
(so, the secret could only be recovered by those users having enough attributes as to satisfy the policy).

In a sense, attribute based encryption generalizes asymmetric cryptography:
the communication is no more 1:1 and the sender (encrypting) could ignore
the users allowed to receive (decrypt) her messages.

An example: document sharing

Assume a company wants to manage the access to certain documents among its employees.
So, the company instantiate an authority company, so that users can ask this authority
for attributes like logistics@company or it@company or topsecret@company.
It is up to the authority to decide whether to give a given attribute-key to a user or not.

A user that needs to encrypt some documents can create a policy like
logistics@company \/ topsecret@company (meaning that the policy is meant to grant
access rights to those user having keys for logistics@company or for topsecret@company),
and use this policy to encrypt the documents.
Now, the authorization layer to the documents is embedded in the mathematics,
meaning that only those users having the appropriate keys will be able
to decrypt the documents.

Policy can also include linear constraints on non-negative integer-valued attributes,
so, users can ask for attributes like level@company with some value from 0 onwards,
to be used in a policy like topsecret@company \/ (level@company > 0 )

The scheme implemented

The code implements the Multi-Authority CipherText-Policy scheme as described in
Efficient Statically-Secure Large-Universe Multi-Authority
Attribute-Based Encryption
by Yannis Rouselakis and Brent Waters.

Specifically, the implementation

  • is based on elliptic curves pairings, powered by miracl (recommended) (code included in this repo) or pbc (including parts of the Go wrapper https://github.com/Nik-U/pbc) [rf. to config file later in this doc]
  • uses linear secret sharing schemes as explained in section G of Decentralizing Attribute-Based Encryption by Allison Lewko and Brent Waters
  • allows numerical expressions in policies (see paragraph below) using
    a bag-of-bits representation of attributes as in Ciphertext-Policy Attribute-Based Encryption by John Bethencourt, Amit Sahai, Brent Waters
  • uses z3 to verify, simplify and rewrite policies (it could use z3 also to solve and get hints from policies)
  • collects the authorities into organizations: policy are allowed to mention only attributes from authorities within a given organization
  • uses an elementary hash-to-group function to map attribute and user strings to the group

Syntax for attributes and policies:

  • boolean attributes are in the form attribute@authority (cfr. notation already used in Charm)
  • integer-valued attributes are written attribute=value@authority
  • policies are arbitrary expressions in attributes with operators /\ (AND) and \/ (OR)
  • policies allow == < <= > >= between an attribute (on the left) and a numerical value (on the right)
  • supporting also S-expressions for policies

APIs

To use the library in a Go environment

  1. import "github.com/marcellop71/mosaic/abe"

Core Go APIs are wrapped by JSON APIs so that every function
has only string type parameters as inputs and outputs
(string could be a plain or a JSON string depending on the function).

Everything binary is encoded to base32
(both JSON strings and field values in JSON objects).

Given the JSON APIs, the library could also be exported as a shared object (resulting in libmosaic.h and libabe.so in ./lib usable by many languages). The wrapping is trivial because there are only char* in each signature.

  1. go build -tags=z3,miracl -buildmode c-shared -o lib/libmosaic.so lib/mosaic.go

(or lib/mosaic_pbc.go)

GO API GO API (JSON) C API
NewRandomOrg (lib string, curve Curve) Org NewRandomOrgJson(string, string) string newRandomOrg
NewRandomAuth(org Org) AuthKeys NewRandomAuthJson(string) string newRandomAuth
NewRandomUserkey(user string, attr string, authprv AuthPrv) Userkey NewRandomUserkeyJson(string, string, string) string newRandomUserkey
NewRandomSecret(org Org, seed string) Point NewRandomSecretJson(string, string) string newRandomSecret
AuthPubsOfPolicy(policy string) AuthPubs AuthPubsOfPolicyJson(string) string authpubsOfPolicy
PolicyOfCiphertext(ct Ciphertext) string PolicyOfCiphertextJson(string) string policyOfCiphertextJson
SelectUserAttrs(user string, policy string, userattrs Userattrs) Userattrs SelectUserAttrsJson(string, string, string) string selectUserAttrs
Encrypt(secret Point, policy string, authpubs AuthPubs) string EncryptJson(string, string, string) string encrypt
Decrypt(ct Ciphertext, userattrs Userattrs) Point DecryptJson(string, string) string decrypt
RewritePolicy(policy string) string RewritePolicy(string) string rewritePolicy
CheckPolicy(policy string, userattrs Userattrs) string CheckPolicyJson(string, string) string checkPolicy
GetPbcCurve(curve string) Curve GetPbcCurve(string) string getPbcCurve

RewritePolicy and CheckPolicy needs z3 support, while GetPbcCurve needs pbc.
Please remark that the support by z3 and miracl (or pbc) is managed by the build tags “z3”, “miracl” and “pbc”. For example, run the example with

  1. go run -tags=z3,miracl examples/ex_JsonAPI.go

Here, the signature is described by a suffix Str (plain string)
or Json (json string, for the objects serialized as json strings).

export signature json schema for output
newRandomOrg libStr, CurveJson (empty if not pbc) -> orgJson json to be used as-is
newRandomAuth orgJson -> authkeysJson { "authpub": "authority public key json string", "authprv": "authority private key json string"}
newRandomUserkey userStr, attrStr, authprvJson -> userattrsJson {"user": "user string", "coeff": {"attribute0": [], ...}, "userkey": {"attribute0": "userkey json string", ...}}
newRandomSecret orgJson, seedStr -> secretStr plain string
rewritePolicy policyStr -> policyStr plain string
checkPolicy policyStr, userattrsJson (possibly empty) -> string {“sat”, “unsat”} plain string
extractAuthsFromPolicy policyStr -> authpubsJson {"authpub": {"authority0": "authority public key", "authority1": "authority public key json string", ...}}
extractPolicyFromCiphertext ciphertextJson -> policyStr plain string
selectUserAttrs userStr, policyStr, userattrsJson -> userattrsJson {"user": "user string", "coeff": {"attribute0": [], ...}, "userkey": {"attribute0": "userkey json string", ...}}
encrypt secretJson, policyStr, authpubsJson -> ciphertextJson json to be used as-is
decrypt ciphertextJson, userattrsJson -> secretStr plain string
getPbcCurve (only for pbc) curveStr -> CurveJson json to be used as-is

The json strings returned by getCurve, newRandomOrg and encrypt are meant to be used as-is: stored somewhere or re-fed into the relevant functions.

An application needs to interact only with authkeysJson, authpubsJson and userattrsJson.
authkeysJson holds the public and private keys for a new authority.
authpubsJson is a json holding in the key ‘authpub’ the association between an authority (name)
and its corresponding public key, while userattrsJson holds the associations
between an attribute and its use (coefficent) in the key “coeff” and
between an attribute and its corresponding user key in the key “key”.

  1. type Org struct { ... } // organization
  2. type AuthPub struct { ... } // authority public params
  3. type AuthPrv struct { ... } // authority private params
  4. type Userkey struct { ... } // user key
  5. type Ciphertext struct { ... } // ciphertext encrypting the msg
  6. type AuthKeys struct { // authority public and private keys
  7. AuthPub string `json:"authpub"` // type AuthPub
  8. AuthPrv string `json:"authprv"` // type AuthPrv
  9. }
  10. type AuthPubs struct { // map of authorities public keys
  11. AuthPub map[string]string `json:"authpub"` // type AuthPub
  12. }
  13. type UserAttrs struct { // map of user attributes
  14. User string `json:"user"` // user
  15. Coeff map[string][]int `json:"coeff"` // attr -> its coefficients
  16. Userkey map[string]string `json:"userkey"` // Userkey
  17. }

Dependencies

The only external dependency that needs to be available is z3 (optionally, also pbc).

Internally, the Go packages used are: logrus for logging and antlr4 for parsing.

The examples (not the library, see below) use

Dependencies or database support could be easily installed:

  • mac os: brew install z3 and brew install leveldb redis (in case also, brew install pbc)
  • linux: see ./docker/Dockerfile

Docker

You can build a docker images with everything:

  1. ./docker/build_image.sh

Source is made up of 2 Go packages:

  • abe: core package defining basic types and the cryptographic scheme
  • service: service package defining interactions with databases

The file structure of the core lib is the following:

file description
arith_miracl.go miracl interface
arith_pbc.go pbc interface
crypto.go ABE scheme algorithms and JSON APIs
policy_z3.go policy management using z3
policy.go parsing and policy management
sss.go linear secret sharing scheme
types.go structs and their serialization
Policy.g4 antlr4 parser grammar
PolicyLexer.g4 antlr4 lexer grammar
log/ logging
miracl/ miracl core library (Go version)
parser/ policy parser (generated by antlr4 using the ./abe/policy.g4 grammar file)
pbc/ pbc library wrapper
z3/ z3 library wrapper

Examples

An ./examples/ex_GoAPI_noservice_noz3.go is there to show how the APIs could be used.
The aim is to encrypt a secret according to a given policy (iterating
over a small set of policies) and recover it (if feasible),
according to a selection of attributes given to a user.

  1. go run -tags=z3,miracl examples/ex_GoAPI_noservice_noz3.go

or

  1. docker run -it mosaic:latest go run -tags=z3,miracl examples/ex_GoAPI_noservice_noz3.go

Storage

./examples/ex_GoAPI_noservice_noz3.go is an application using the github.com/mosaic/abe package
and a ./mosaic/service package to handle some storage for the keys,
the attributes and the users.
The service package implemented can use Leveldb
or a Redis server.
Details in the configuration file ./examples/config.yaml

  1. config:
  2. arithmetic:
  3. library: miracl
  4. curve: BN254
  5. seed: abcdef
  6. storage:
  7. redis:
  8. local0:
  9. addr: "127.0.0.1:6379"
  10. password: ""
  11. leveldb:
  12. local0:
  13. name: "mosaic.db"
  14. active:
  15. type: "leveldb"
  16. label: "local0"

Workflow

The workflow implemented in the example is basic.
Using attribute based encryption for a document sharing application
could mean that an encryptor:

  • creates a random secret
  • uses this secret to encrypt (symmetric) a document
  • creates a policy string describing access to the document
  • creates an encrypted version secret_enc of the secret according to the policy
  • shares the encrypted document and the secret_enc + an hashed version of the secret secret_hash

now if a user needs to access the document:

  • user asks an authority for its keys corresponding to a given attribute
  • user decrypts the secret_enc into a clear secret
  • user checks if she can recover the secret_hash
  • user uses this secret to decrypt the document

Setup curve, organization and authorities

  1. service.SetupOrg("org0", "miracl", "BN254", seed) // setting up an organization (hosting a set of authorities) onto a given curve
  2. service.SetupAuth("auth0", "org0") // setting up an authority into a given organization

Using boolean policies

  1. policy := "A@auth0 /\\ (B@auth0 /\\ (C@auth0 \\/ D@auth0))" // a policy as a standard boolean expression
  2. // encrypting
  3. secret := service.NewRandomSecret("org0") // create a new secret
  4. policy = abe.RewritePolicy(policy) // simplify policy
  5. auths := abe.AuthPubsOfPolicyJson(policy) // extracts authorities mentioned in the policy
  6. auths = service.FetchAuthPubs(auths) // collects public keys of those authorities
  7. secret_enc := abe.EncryptJson(secret, policy, auths) // encrypts the secret into a ciphertext
  8. // user asking for keys
  9. user := "marcello.paris@gmail.com"
  10. service.SetupUserkey(user, "A@auth0") // for the user creates a key corresponding to the given attribute
  11. service.SetupUserkey(user, "B@auth0") // for the user creates a key corresponding to the given attribute
  12. service.SetupUserkey(user, "C@auth0") // for the user creates a key corresponding to the given attribute
  13. service.SetupUserkey(user, "D@auth0") // for the user creates a key corresponding to the given attribute
  14. // decrypting
  15. policy = abe.PolicyOfCiphertextJson(secret_enc) // extract the policy embedded in the ciphertext
  16. userattrs := service.FetchUserAttrs(user) // collects the available user attributes
  17. userattrs = abe.SelectUserAttrsJson(user, policy, userattrs) // select which user attributes (if any) are useful for the given policy
  18. userattrs = service.FetchUserkeys(userattrs) // collects user keys corresponding to the useful attributes
  19. secret_dec := abe.DecryptJson(secret_enc, userattrs) // decrypts the ciphertext into the secret plaintext

Integer-valued attributes

  1. policy := "(A@auth0 > 1) /\\ B@auth0"
  2. ...
  3. service.SetupUserkey(user, "A=5@auth0")

Curves and pairings

Use “BN254” or “BLS12381” or “BN462” if using miracl (recommended)
or use “SS512” or “BN254” if using pbc.

Let the pairing be G1 x G2 -> GT

The scheme encrypts a point in GT as:

  • a point on GT (the point to be encrypted perturbed by a secret)
  • a bags of 4-points tuples (i.e., bag of points on GT x G1 x G1 x G2) [one tuple for each attribute-leave in the policy]