Building A New World of Security With Zero Trust, Trusted Attributes and Claims

We have now started a new collaboration with MIRACL, and aim to build systems that have high levels of trust and implement a zero-trust…

Photo by Peter Burdon on Unsplash

Building A New World of Security With Zero Trust, Trusted Attributes and Claims

We have now started a new collaboration with MIRACL, and aim to build systems that have high levels of trust and implement a zero-trust environment. Along with this, we aim to implement the latest methods in Zero Knowledge Proofs and Homomorphic Encryption (along with adopting the latest Post Quantum Cryptography). In this article, we will investigate the usage of trusted attributes to encrypt a file, and then use a cipher policy to unlock it.

Old-world, new-world

There’s an old world of security, and there’s a new world. Our old world is based on mapping users to roles and then defining the rights of the user dependent on their role. Unfortunately, this becomes complex once we scale our system up, and can often give generalised access to those who do not need it. To simplify, we can generalise the roles, but, again, we can give access to things that are not actually required. For example, we might have staff and students as a role and keep things simple. But, we now need to provide all staff with given rights, and all students with another set of rights. In most systems, we end up with multiple roles where each gives their own rights, and might even conflict with each other.

Attributes, claims and enforcement policies

But, the greatest problem is role-based security, is that we do not take into account the location of a person or the time of the day. Thus a role might be part of the claim to access a service, but we can also define attributes that can be used to further claim access. For this we can implement an attribute-based approach, and define these attributes in a policy. In order to unlock the policy with encryption, we can encrypt data so that the user needs to provide attribute claims which match to a cipher policy.

This means that we could have a movie that can only be seen in a specific country and at a specific time. If the user can provide proof of their location and the current time, they can gain access to the encryption key which can decrypt the movie. If not, the user will be locked out.

Another major weakness in many systems is that the operating system is often used to protect access to a file. This approach is weak for many reasons, including the ability to access a file without the operating system lock. To overcome this, CP-ABE aims to encrypt the file, so that there is no need to rely on the operating system to lock the file.

CP-ABE (Cipher Policy — Attributed-Based Encryption)

With CP-ABE, we can generate an encryption key based on a policy and a set of attributes. In this case, we can only generate the correct decryption key with the right attributes. The policy we will implement is:

 ((location: edinburgh) and (service: payment)) or (role: admin))

This means that if the user is in Edinburgh and is making a payment, then they will be able to decrypt an encrypted message. They will also be able to decrypt it, if they have an “admin” role. All other cases will not allow the encryption key to be created.

The method we will use has been defined by Tomida et al [1]:

With this method, we create a public key to encrypt our messages, and then a secret (private) key to decrypt it. Only when the user can provide the required attributes to match the policy, can we generate the required private key to decrypt the encrypted content. We then end up with a key-policy (KP) and implement a ciphertext-policy (CP) ABE approach. Overall, the KP is processed to identify redundant parts of the policy, such as for:

(location: edinburgh and service: payment) or 
(location: edinburgh or service:withdrawl)

and which becomes:

(location: edinburgh or service:withdrawl)

Coding

The outline code is [here]:

package main
import (
"bytes"
"crypto/rand"
"fmt"
"log"
"os"
cpabe "github.com/cloudflare/circl/abe/cpabe/tkn20"
)
func checkPolicy(in map[string][]string) bool {
possiblePairs := map[string][]string{
"location": {"edinburgh", "glasgow", "stirling"},
"service": {"payment", "withdrawl", "balance"},
"role": {"admin", "production", "sales"},
}
isValid := func(key string, value string) bool {
vs, ok := possiblePairs[key]
if !ok {
return false
}

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() {
argCount := len(os.Args[1:])
msg := `Message`
location:="edinburgh"
service:="payment"
role:="admin"
policyStr := `((location: edinburgh) and (service: payment)) or (role: admin) `
if (argCount>0) {msg= os.Args[1]}
if (argCount>1) {location= os.Args[2]}
if (argCount>2) {role= os.Args[3]}
if (argCount>3) {service= os.Args[4]}
if (argCount>4) {policyStr= os.Args[5]}

attrsMap := map[string]string{"location":location, "service": service, "role": role}
fmt.Printf("Policy: %s\n",policyStr)
fmt.Printf("Attributes. Location: %s, Service: %s, Role: %s\n\n",location,service, role)
publicKey, secretKey, err := cpabe.Setup(rand.Reader)
if err != nil {
log.Fatalf("%s", err)
}
p,_:=publicKey.MarshalBinary()
fmt.Printf("Public key (64 bytes): %+x\n",p[:64] )
p,_=secretKey.MarshalBinary()
fmt.Printf("Private key (64 bytes): %+x\n",p[:64] )
policy := cpabe.Policy{}
err = policy.FromString(policyStr)
if err != nil {
fmt.Printf("\nError in policy")
}
if checkPolicy(policy.ExtractAttributeValuePairs()) {
fmt.Printf("\nPolicy works\n")
}

ct, _ := publicKey.Encrypt(rand.Reader, policy, []byte(msg))

attributes := cpabe.Attributes{}
attributes.FromMap(attrsMap)
SecretKey, _ := secretKey.KeyGen(rand.Reader, attributes)

rightSat := policy.Satisfaction(attributes)
if !rightSat {
fmt.Printf("\nAttributes match policy")
}
canDecrypt := attributes.CouldDecrypt(ct)
if canDecrypt == true {
fmt.Printf("\nDecryption should work")
}

pt, _ := SecretKey.Decrypt(ct)
if !bytes.Equal(pt, []byte(msg)) {
fmt.Printf("\nPlaintext not recovered")
} else {
fmt.Printf("\nPlaintext recovered successfully: %s", pt)
}

}

Overall, it uses pairing-based cryptography to implement the policy. We thus have a public key (pk), a secret key (sk) and ciphertext (ct):

And where we have n labels in the policy (and each denoted by i), with alpha being the overall secret. If you want to learn more about pairing-based cryptography, try here. For something that matches the policy [here]:

Policy: ((location: edinburgh) and (service: payment)) or (role: admin) 
Attributes. Location: edinburgh, Service: payment, Role: sales
Public key (64 bytes): 040604000200151468347a05d99fea93226a6cb8e27a08d701fe1403d82bc2c91e5c0dfaf5e98d85dce43f1e337989b5a9d4dfcb39e0105b9aaa8b763825fec2
Private key (64 bytes): c400030002000f4c4f86d6b8bb1e19131e71898c6eed7fe0ceddd6fc40429cc7b2f534389f0d0000000000000000000000000000000000000000000000000000
Policy works
Decryption should work
Plaintext recovered successfully: My message

and for “admin” [here]::

Policy: ((location: edinburgh) and (service: payment)) or (role: admin) 
Attributes. Location: glasgow, Service: payment, Role: admin
Public key (64 bytes): 0406040002001769642282666a2cc054b059b3785d38397e4871c216f3aaf292ca3e6fbf01b885c65038712a141f5dd5bf413efedceb0230b77e3ce1367fb8a9
Private key (64 bytes): c4000300020073ba919191d5aa357cd57670c9da805f810da99141c598a07bb1d44acdce06210000000000000000000000000000000000000000000000000000
Policy works
Decryption should work
Plaintext recovered successfully: My message

and a policy that does not match [here]:

Policy: ((location: edinburgh) and (service: payment)) or (role: admin) 
Attributes. Location: stirling, Service: payment, Role: production
Public key (64 bytes): 040604000200010eff9555a2c03f8b8488c8eb32db7daa853454d897a03218f82c168ae43ee65541b15cda9b845e35b5e25cef0aa144026dd869a63c56d2f216
Private key (64 bytes): c40003000200499b969f303bf8a18d0855056b296925d218392aae8f1492da26152edbe233b50000000000000000000000000000000000000000000000000000
Policy works
Attributes match policy
Plaintext not recovered

Conclusions

We are so happy to work with an international leader in pairing-based cryptography: MIRACL and hope to build a new generation of access control systems. These will be based on zero trust, and a strong enforcement of attribute-based policies.

References

[1] Tomida, J., Kawahara, Y., & Nishimaki, R. (2021). Fast, compact, and expressive attribute-based encryption. Designs, Codes and Cryptography, 89, 2577–2626. https://eprint.iacr.org/2019/966