134 lines
7.1 KiB
Markdown
134 lines
7.1 KiB
Markdown
|
# Implicit Certificate
|
|||
|
|
|||
|
This section will illustrate a Zencode implementation of the Elliptic Curve Qu-Vanstone implicit certificate scheme (ECQV) as described by the Standards for Efficient Cryptography 4 (SEC4, 2014).
|
|||
|
|
|||
|
> The ECQV implicit certificate scheme is intended as a general purpose certificate scheme for applications within computer and communications systems. It is particularly well suited for application environments where resources such as bandwidth, computing power and storage are limited. ECQV provides a more efficient alternative to traditional certificates.
|
|||
|
|
|||
|
The ECQV is identifiable as a simple yet important building block within DECODE, as it permits the efficient creation of certiciates that contain only the public reconstruction data instead of the subject’s public key and the CA’s signature, also resulting into a smaller payload than traditional certificates.
|
|||
|
|
|||
|
ECQV relates well to those DECODE pilots in need to authenticate participants according to signed credentials, where the issuance of a public key is subject to the verification of certain conditions by a Certificate Authority (CA) capable of verifying and signing those conditions. This scenarios applies well to the pilot experimentations ongoing in Amsterdam for the DECODE project, where a certificate (and a keypair) is issued based on attributes that are certified by the municipal register and then used for authentication procedures operated by third parties and based on those attributes.
|
|||
|
|
|||
|
The limit of this implementation is the lack of decentralization, a problem that will be solved by the Coconut [cit] implementation in Zencode language, which is still a work in progress.
|
|||
|
|
|||
|
## Differences with traditional certificates
|
|||
|
|
|||
|
To justify the implementation and adoption of ECQV in place of traditional certificates, here are quickly listed three salient characteristcs, closely referring to the documentation offered by the SEC4-1.0 document.
|
|||
|
|
|||
|
With traditional certificates, when an entity U requests a traditional certificate for a public key, U should prove to the CA it knows the corresponding private key. This is to prevent U from choosing an arbitrary public key, that may already belong to another user, and have it certified. This situation is clearly undesirable (and may even lead to security problems). With implicit certificates this proof is unnecessary, as there is no public key before the certificate is issued. Further, U has no control over the final value of his public key, due to the CA’s contribution, making it impossible for U to cause the confusion described above.
|
|||
|
|
|||
|
Unlike traditional certificates, an implicit certificate does not contain a digital signature. In fact, one could simply choose an arbitrary identity I and a random value to form a certificate. Together with the public key of a CA, this generates a public key for the entity identified by I. However, if one constructs an implicit certificate in such a way, i.e., without interacting with the CA, it is infeasible to compute the private key that corresponds to the public key generated by the certificate.
|
|||
|
|
|||
|
Another difference between traditional certificates and implicit certificates is that when presented with a valid traditional certificate, one knows that the certificate belongs to someone. A valid certificate containing the certificate data string IU is a proof that the CA signed this certificate for U , and also that U knows the private key corresponding to the public key included in the certificate. One does not have this guarantee with implicit certificates, satisfying certain privacy conditions made evident by the GDPR.
|
|||
|
|
|||
|
## Zencode Implementation
|
|||
|
|
|||
|
This section will demonstrate the Zencode implementation in four
|
|||
|
steps, covering all the transformations into a human-readable language
|
|||
|
from the mathematical formula to the implementation capable of being
|
|||
|
executed in the Zenroom VM without any external dependency.
|
|||
|
|
|||
|
The first step is the mathematical formula for ECQV as explained in
|
|||
|
the SEC4 document.
|
|||
|
|
|||
|
![Mathematical formulation of the ECQV implicit certificate scheme](ecqv.png)
|
|||
|
|
|||
|
The second step is the implementation of this formula into the machine
|
|||
|
language executed by the Zenroom VM (a dialect of LUA).
|
|||
|
|
|||
|
```lua
|
|||
|
-- Zenroom 0.8.0
|
|||
|
-- setup
|
|||
|
random = RNG.new()
|
|||
|
order = ECP.order()
|
|||
|
G = ECP.generator()
|
|||
|
-- make a request for certification
|
|||
|
ku = INT.new(random, order)
|
|||
|
Ru = G * ku
|
|||
|
-- keypair for CA
|
|||
|
dCA = INT.new(random, order) -- private
|
|||
|
QCA = G * dCA -- public (known to Alice)
|
|||
|
-- from here the CA has received the request
|
|||
|
k = INT.new(random, order)
|
|||
|
kG = G * k
|
|||
|
-- public key reconstruction data
|
|||
|
Pu = Ru + kG
|
|||
|
declaration = { public = Pu:octet(),
|
|||
|
requester = str("Alice"),
|
|||
|
statement = str("I am stuck in Wonderland.") }
|
|||
|
declhash = sha256(OCTET.serialize(declaration))
|
|||
|
hash = INT.new(declhash, order)
|
|||
|
-- private key reconstruction data
|
|||
|
r = (hash * k + dCA) % order
|
|||
|
-- verified by the requester, receiving r,Certu
|
|||
|
du = (r + hash * ku) % order
|
|||
|
Qu = Pu * hash + QCA
|
|||
|
assert(Qu == G * du)
|
|||
|
```
|
|||
|
|
|||
|
The third step is the improvement of the previous implementation using
|
|||
|
meaningful variable and function names.
|
|||
|
|
|||
|
|
|||
|
```lua
|
|||
|
-- Zenroom 0.8.1
|
|||
|
-- setup
|
|||
|
random = RNG.new()
|
|||
|
order = ECP.order()
|
|||
|
G = ECP.generator()
|
|||
|
-- typical EC key generation on G1
|
|||
|
function keygen(rng,modulo)
|
|||
|
local key = INT.new(rng,modulo)
|
|||
|
return { private = key,
|
|||
|
public = key * G }
|
|||
|
end
|
|||
|
-- generate the certification request
|
|||
|
certreq = keygen(random,order)
|
|||
|
-- certreq.private is preserved in a safe place
|
|||
|
-- certreq.public is sent to the CA along with a declaration
|
|||
|
declaration = { requester = str("Alice"),
|
|||
|
statement = str("I am stuck in Wonderland") }
|
|||
|
-- Requester sends to CA -->
|
|||
|
-- ... once upon a time ...
|
|||
|
-- --> CA receives from Requester
|
|||
|
-- keypair for CA (known to everyone as the Mad Hatter)
|
|||
|
CA = keygen(random,order)
|
|||
|
-- from here the CA has received the request
|
|||
|
certkey = keygen(random,order)
|
|||
|
-- certkey.private is sent to requester
|
|||
|
-- certkey.public is broadcasted
|
|||
|
-- public key reconstruction data
|
|||
|
certpub = certreq.public + certkey.public
|
|||
|
-- the certification is serialized (could use ASN-1 or X509)
|
|||
|
certification = { public = certpub,
|
|||
|
requester = declaration.requester,
|
|||
|
statement = declaration.statement,
|
|||
|
certifier = str("Mad Hatter") }
|
|||
|
CERT = sha256(OCTET.serialize(certification))
|
|||
|
CERThash = INT.new(CERT, order)
|
|||
|
-- private key reconstruction data
|
|||
|
certpriv = (CERThash * certkey.private + CA.private) % order
|
|||
|
-- CA sends to Requester certpriv and CERThash
|
|||
|
-- eventually CA broadcasts certpub and CERThash
|
|||
|
-- ... on the other side of the mirror ...
|
|||
|
-- Alice has received from the CA the certpriv and CERT
|
|||
|
-- which can be used to create a new CERTprivate key
|
|||
|
CERTprivate = (certpriv + CERThash * certreq.private) % order
|
|||
|
-- Anyone may receive the certpub and CERThash and, knowing the CA
|
|||
|
-- public key, can recover the same CERTpublic key from them
|
|||
|
CERTpublic = certpub * CERThash + CA.public
|
|||
|
-- As a proof here we generate the public key in a standard way,
|
|||
|
-- multiplying it by the curve generator point, then check equality
|
|||
|
assert(CERTpublic == G * CERTprivate)
|
|||
|
print "Certified keypair:"
|
|||
|
I.print({ private = CERTprivate:octet():base64(),
|
|||
|
public = CERTpublic:octet():base64() })
|
|||
|
```
|
|||
|
|
|||
|
At last, the implementation in Zencode follows
|
|||
|
|
|||
|
```
|
|||
|
-- Zenroom 0.8.1
|
|||
|
```
|
|||
|
|
|||
|
|