-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Smartcard support #38
Conversation
45af305
to
4016d78
Compare
This PR implements the protocol from https://eprint.iacr.org/2023/853. The protocol is between 3 parties, a user, a smartcard and a verifier, where user and smartcard can jointly convince a verifier they posses a tuple of attributes, one of which is only known by the smartcard. In the idemix implementation, the smartcard is a NymSigner and the user just produces an idemix signature against the nym generated by the smartcard. The only difference is that - contrary to the traditional idemix signature - the user does not know the usk (used by the smartcard/NymSigner). The protocol adapts the ZKP to cater for this lack of knowledge. Signed-off-by: Alessandro Sorniotti <[email protected]>
4016d78
to
ceb4d6c
Compare
@@ -160,7 +160,10 @@ func (i *NymPublicKeyImporter) KeyImport(raw interface{}, opts bccsp.KeyImportOp | |||
|
|||
pk, err := i.User.NewPublicNymFromBytes(bytes) | |||
if err != nil { | |||
return nil, err | |||
pk, err = i.User.NewPublicNymFromBytes(append([]byte{04}, bytes...)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a comment to clarify why appending that magic number?
Can you put it in a const?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. So, there are several issues here at play. I'll try to summarise them here and maybe you can give me your take on how to best document it? So:
- the
NymPublicKeyImporter
does not have atranslator
to handle the various byte representations of group elements. Instead, it directly passes the bytes to the underlying implementation without any translation. This works well most of the times since actually for most curves, the serialisation of a group element is a fixed-size array of the two coordinates. However some curves use an encoding where the constant byte value0x04
is prefixed to the two coordinates to signal that the point is uncompressed. - it is meaningful to add the translator, but I would do it in a separate change
- prefixing
0x04
cannot turn a bad point marshalling into a good one anyway, unless it's the encoding issue that we are handling.
Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add in the comments points 1 and 2, and then open a github issue for the translator 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// handle the smartcard case | ||
if signerOpts.IsSmartcard { | ||
if s.SmartcardNymSignatureScheme == nil { | ||
return nil, fmt.Errorf("smartcard mode is unsupported") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's always use "github.com/pkg/errors"
, please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually that package has been sunset. Afaik the new go error design prescribes the use of fmt.Errorf
and the %w
modifier. See this thread hyperledger/fabric#4461
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mentioned this because in some other places "github.com/pkg/errors"
is used.
Then, a possible solution would be to create a local errors
package with aliases to the functions you want to use. Then, the code can be refactored to use those aliases.
Up to you :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the "right" choice would be to just follow the new go error proposal and start using just fmt
. There are other active forks of "github.com/pkg/errors"
, that's not even the issue. The issue is rather that if the proper way of handling errors is another one, we shouldn't use them. Let me investigate a bit more, but I think for now we can leave it as is?
@@ -50,7 +54,15 @@ func (s *Signer) getPoKOfSignature( | |||
|
|||
messagesFr := credential.toSignatureMessage(sk, s.Curve) | |||
|
|||
pokOS, err := bbs12381g2pub.NewBBSLib(s.Curve).NewPoKOfSignature(signature, messagesFr, revealedAttributesIndex(attributes), ipk) | |||
var pokOS *bbs12381g2pub.PoKOfSignature | |||
if sigtype == types.Smartcard { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add a comment to explain the difference between the two cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
func (sc *Smartcard) NymEid() (*math.Zr, *math.G1) { | ||
// increment counter | ||
sc.ctr++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make sure: Smartcard should not be assumed to be thread-safe. Is this written anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah so this code is just a smartcard emulator to test the e2e without any separate hardware. How do you think we should capture that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually - a clarification: the signing part of that function is just a mock - because signing actually needs to be performed by the smartcard. The verification part instead is meaningful and used - see also next comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then, please could you a comment to the Smartcard
struct to mention that it is used as an emulator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -35,6 +32,32 @@ func (s *NymSigner) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) ([]b | |||
return nil, errors.New("invalid issuer public key, expected *issuerPublicKey") | |||
} | |||
|
|||
// handle the smartcard case | |||
if signerOpts.IsSmartcard { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this part of the code is not tested, can it be without an actual smartcard?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah exactly, that's tricky. This particular code is only a wrapper to call
https://github.com/IBM/idemix/blob/smartcard-squash/bccsp/schemes/aries/smartcard.go#L116
It's difficult to test that from the bccsp layer since it would require the creation of a mock bccsp smartcard signer. Otoh we do test it from here using the emulated signing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually I'm sorry - I wrote this code a while back so I forgot: I double-checked and we DO test this - just not from this package: In particular, this line
https://github.com/IBM/idemix/blob/smartcard-squash/bccsp/smartcard_test.go#L264
ends up testing exactly this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perfect 👍
@@ -3,9 +3,9 @@ module github.com/IBM/idemix | |||
go 1.19 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about moving to 1.21. Go 1.19 is deprecated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point - yes. Given that I have one more functional PR on top of this one, would it be okay to merge this, the next, and then upgrade to go 1.21?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure 👍
IsSmartcard bool | ||
|
||
// Smartcard is a software smartcard used to support signing in s/w | ||
Smartcard interface{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is interface{} the best we can have? It might cause issues with serialisation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I double-checked (to find out the correct answer to #38 (comment)) and in doing so I established that we use this only in testing to simulate a smartcard nym signer backed by the CSP in order to then be able to test the nym verifier of smartcard-created nym signatures without the actual smartcard. So this will never be set in production.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perfect 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment though
Signed-off-by: Alessandro Sorniotti <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Signed-off-by: Alessandro Sorniotti <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This PR implements the protocol from https://eprint.iacr.org/2023/853. The protocol is between 3 parties, a user, a smartcard and a verifier, where user and smartcard can jointly convince a verifier they posses a tuple of attributes, one of which is only known by the smartcard. In the idemix implementation, the smartcard is a NymSigner and the user just produces an idemix signature against the nym generated by the smartcard. The only difference is that - contrary to the traditional idemix signature - the user does not know the usk (used by the smartcard/NymSigner). The protocol adapts the ZKP to cater for this lack of knowledge.