attestation
attestation copied to clipboard
produce a view function to test useDevconTicket
which has
getTicketHolderAddress(bytes UseDevconTicket)
The contract has to be deployed with the issuer's public key. Source code of the contract goes to src/main/solidity
. (the capacity to update such key can be added later).
It returns the ticket holder's address. Such an address can be obtained by:
Get the public key in SEC1 2.3.4 format
UseDevconTicket.MyAttestation
.subjectPublicKeyInfo
.subjectPublicKeyInfoValue
.subjectPubilicKey
Get the Ethereum address
- check if the leading byte is 0x04 - throw up if it isn't (unless you are keen on implementing the full SEC1 spec)
- remove the leading byte and Keccek3 hash the rest 64 bytes
- return the first 160 bites as Ethereum address
Verifying UseDevconTicket
The zk proof in it must be verified otherwise the view function should err.
DevconTicket
The smart contract also must verify the DevconTicket otherwise the view function should err.
https://github.com/TokenScript/attestation/blob/main/data-modules/src/UseDevconTicket.asd
which contains SignedDevconTicket, which can be found here:
$ openssl asn1parse -inform DER < build/test-results/signed-devcon-ticket.der
0:d=0 hl=3 l= 153 cons: SEQUENCE
3:d=1 hl=2 l= 11 cons: SEQUENCE
5:d=2 hl=2 l= 1 prim: INTEGER :06
8:d=2 hl=2 l= 3 prim: INTEGER :BE06
13:d=2 hl=2 l= 1 prim: INTEGER :00
16:d=1 hl=2 l= 65 prim: OCTET STRING [HEX DUMP]:04206430CAE202E5FAB41CE54B74725E454FF808720A039037D8403D95FEFDC035122C95BFD2AE1A48A3F42F0B8E78FB792351ADE20A2209A31F4E90DC61A4D50F
83:d=1 hl=2 l= 71 prim: BIT STRING
You can open it up with javascript:
$ nodejs src/test/javascript/ParserSerializerTest.js
SignedDevconTicket {
ticket: DevconTicket { devconId: 6n, ticketId: 48646n, ticketClass: 0n },
commitment: ArrayBuffer {
[Uint8Contents]: <04 20 64 30 ca e2 02 e5 fa b4 1c e5 4b 74 72 5e 45 4f f8 08 72 0a 03 90 37 d8 40 3d 95 fe fd c0 35 12 2c 95 bf d2 ae 1a 48 a3 f4 2f 0b 8e 78 fb 79 23 51 ad e2 0a 22 09 a3 1f 4e 90 dc 61 a4 d5 0f>,
byteLength: 65
},
publicKeyInfo: PublicKeyInfo { signatureAlgorithm: undefined, publicKey: undefined },
signatureValue: ArrayBuffer {
[Uint8Contents]: <30 44 02 20 38 db 21 b6 b5 b7 c6 92 da ad a2 b6 2e bb 89 e5 a3 6e 3a 3c ce 66 1e 38 53 2b c9 ac c8 5c 34 1b 02 20 70 46 73 21 8f 77 b2 47 b5 51 ab 3c 3d 74 e1 ef 8f 4f 7e 3a e0 40 1d 53 54 26 65 3a aa 5e c2 a2>,
byteLength: 70
}
}
SignedDevconTicket {
ticket: DevconTicket {
devconId: 6n,
ticketId: 417541561855n,
ticketClass: 0n
},
commitment: ArrayBuffer {
[Uint8Contents]: <04 07 02 50 ca 69 74 01 95 f9 31 f3 35 4c ca ba b8 72 4f 9d 98 e9 cd 8a d9 b0 8b 68 c1 e3 b3 9f ab 16 2c ef f4 a8 64 67 8b 1d 02 4d 78 64 77 3c 9f 0f fa 77 be 8d 54 6e 8d 83 34 88 48 41 03 c0 3a>,
byteLength: 65
},
publicKeyInfo: PublicKeyInfo { signatureAlgorithm: undefined, publicKey: undefined },
signatureValue: ArrayBuffer {
[Uint8Contents]: <30 44 02 20 70 2c af bd e4 d3 d9 a3 45 b4 d4 70 c1 7f 26 62 b1 9d 8a 68 da f3 a1 6b b1 45 5f e7 86 31 8b 30 02 20 68 e3 f8 79 55 48 34 7e 71 33 c0 af f4 e5 43 77 23 86 dc 1c 54 ab 23 d5 40 eb 83 53 d3 da 0b da>,
byteLength: 70
}
}
And notice the last byte array is the signature, you can get the asn1 structure through this:
0:d=0 hl=2 l= 68 cons: SEQUENCE
2:d=1 hl=2 l= 32 prim: INTEGER :702CAFBDE4D3D9A345B4D470C17F2662B19D8A68DAF3A16BB1455FE786318B30
36:d=1 hl=2 l= 32 prim: INTEGER :68E3F8795548347E7133C0AFF4E543772386DC1C54AB23D540EB8353D3DA0BDA
So the first integer and the second integer are 𝑟 and 𝑠
You need to figure out a way of finding 𝑣 from a public key.
You can create a key like this:
$ openssl ecparam -name secp256k1 -genkey -noout -out key.pem
and read the value:
$ openssl ec -in key.pem -pubout -text
read EC key
Private-Key: (256 bit)
priv:
05:89:22:6f:f7:e5:b6:bf:b7:79:57:af:0a:b2:66:
9a:37:3c:80:7d:e1:e7:ee:bb:7f:51:53:ba:c0:79:
0d:4b
pub:
04:03:72:92:0b:c5:f2:92:ae:80:2f:f4:42:ed:e7:
77:61:3a:af:13:ca:89:4b:9a:78:a1:01:d2:87:46:
2e:17:a4:3e:b2:2d:dc:95:af:ae:31:5a:90:a2:0e:
cb:1e:c4:56:97:2c:31:9a:c9:4c:00:b5:f0:66:dc:
b1:dd:e5:64:02
ASN1 OID: secp256k1
writing EC key
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEA3KSC8Xykq6AL/RC7ed3YTqvE8qJS5p4
oQHSh0YuF6Q+si3cla+uMVqQog7LHsRWlywxmslMALXwZtyx3eVkAg==
-----END PUBLIC KEY-----
Note that the public key here is not in ASN1 format! It's format is specified in SEC1 2.3.4 (if you want to sound professional, it's S.E.C. one, two, three, four) https://www.secg.org/sec1-v2.pdf#page=18
which is explained in plain English here: https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm
@jot2re how to get the 𝑣 value from this or the version with leading 04 stripped (which is Ethereum preferred method )
Note that PR #89 changes the UseDevconTicket ticket to make signature optional and to use a Proof that does not include the riddle.
I looked up a bit further in the SEC1 spec. Basically 3 bytes are allowed to prefix an elliptic curve point. The cases are as follows:
- 0x04; the point is uncompressed and includes the concatenation of the X coordinate followed by the Y coordinate.
- 0x02; the point is compressed and only includes the X coordinate and the parity of the Y coordinate is 0 (i.e. Y mod 2 =0).
- 0x03; the point is compressed and only includes the X coordinate and the parity of the Y coordinate is 1 (i.e. Y mod 2 =1).
Thus depending on whether 0x02 or 0x03 is the initial byte it is possible to uniquely determinate the correct value of Y from the X coordinate alone.
The big question is if the same logic is used for the v point in Ethereum. I googled a bit and finally found a description of how v is computed. According to (this discussion)[https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v] v=27+(y mod 2). Thus slightly different than the key encoding, but still easy to adapt.
𝑦 mod 2
Nice! So @JamesSmartCell should be able to find 𝑣 value by just looking at the devcon issuer public key's last bit.