Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
IRMA
Github mirrors
irmago
Commits
db143b0b
Commit
db143b0b
authored
Jan 29, 2019
by
Sietse Ringers
Browse files
Merge branch 'paillier'
parents
2c58b9be
d148654b
Changes
7
Hide whitespace changes
Inline
Side-by-side
Gopkg.toml
View file @
db143b0b
...
...
@@ -24,11 +24,6 @@
# go-tests = true
# unused-packages = true
[[constraint]]
branch
=
"master"
name
=
"github.com/credentials/go-go-gadget-paillier"
[[constraint]]
branch
=
"master"
name
=
"github.com/getsentry/raven-go"
...
...
descriptions.go
View file @
db143b0b
...
...
@@ -57,6 +57,7 @@ type CredentialType struct {
AttributeTypes
[]
*
AttributeType
`xml:"Attributes>Attribute" json:"-"`
XMLVersion
int
`xml:"version,attr"`
XMLName
xml
.
Name
`xml:"IssueSpecification"`
IssueURL
TranslatedString
`xml:'IssueURL'`
Valid
bool
`xml:"-"`
}
...
...
irmaclient/client.go
View file @
db143b0b
package
irmaclient
import
(
"crypto/rand"
"sort"
"strconv"
"time"
"github.com/credentials/go-go-gadget-paillier"
raven
"github.com/getsentry/raven-go"
"github.com/go-errors/errors"
"github.com/privacybydesign/gabi"
...
...
@@ -45,7 +42,6 @@ type Client struct {
attributes
map
[
irma
.
CredentialTypeIdentifier
][]
*
irma
.
AttributeList
credentialsCache
map
[
irma
.
CredentialTypeIdentifier
]
map
[
int
]
*
credential
keyshareServers
map
[
irma
.
SchemeManagerIdentifier
]
*
keyshareServer
paillierKeyCache
*
paillierPrivateKey
logs
[]
*
LogEntry
updates
[]
update
...
...
@@ -174,12 +170,6 @@ func New(
if
cm
.
keyshareServers
,
err
=
cm
.
storage
.
LoadKeyshareServers
();
err
!=
nil
{
return
nil
,
err
}
if
cm
.
paillierKeyCache
,
err
=
cm
.
storage
.
LoadPaillierKeys
();
err
!=
nil
{
return
nil
,
err
}
if
cm
.
paillierKeyCache
==
nil
{
cm
.
paillierKey
(
false
)
}
if
len
(
cm
.
UnenrolledSchemeManagers
())
>
1
{
return
nil
,
errors
.
New
(
"Too many keyshare servers"
)
...
...
@@ -202,7 +192,6 @@ func (client *Client) CredentialInfoList() irma.CredentialInfoList {
}
}
sort
.
Sort
(
list
)
return
list
}
...
...
@@ -687,32 +676,6 @@ func (client *Client) ConstructCredentials(msg []*gabi.IssueSignatureMessage, re
// Keyshare server handling
// PaillierKey returns a new Paillier key (and generates a new one in a goroutine).
func
(
client
*
Client
)
paillierKey
(
wait
bool
)
*
paillierPrivateKey
{
cached
:=
client
.
paillierKeyCache
ch
:=
make
(
chan
bool
)
// Would just write client.paillierKeyCache instead of cached here, but the worker
// modifies client.paillierKeyCache, and we must be sure that the boolean here and
// the if-clause below match.
go
client
.
paillierKeyWorker
(
cached
==
nil
&&
wait
,
ch
)
if
cached
==
nil
&&
wait
{
<-
ch
// generate yet another one for future calls, but no need to wait now
go
client
.
paillierKeyWorker
(
false
,
ch
)
}
return
client
.
paillierKeyCache
}
func
(
client
*
Client
)
paillierKeyWorker
(
wait
bool
,
ch
chan
bool
)
{
newkey
,
_
:=
paillier
.
GenerateKey
(
rand
.
Reader
,
2048
)
client
.
paillierKeyCache
=
(
*
paillierPrivateKey
)(
newkey
)
client
.
storage
.
StorePaillierKeys
(
client
.
paillierKeyCache
)
if
wait
{
ch
<-
true
}
}
func
(
client
*
Client
)
genSchemeManagersList
(
enrolled
bool
)
[]
irma
.
SchemeManagerIdentifier
{
list
:=
[]
irma
.
SchemeManagerIdentifier
{}
for
name
,
manager
:=
range
client
.
Configuration
.
SchemeManagers
{
...
...
@@ -754,15 +717,14 @@ func (client *Client) keyshareEnrollWorker(managerID irma.SchemeManagerIdentifie
}
transport
:=
irma
.
NewHTTPTransport
(
manager
.
KeyshareServer
)
kss
,
err
:=
newKeyshareServer
(
managerID
,
client
.
paillierKey
(
true
),
manager
.
KeyshareServer
)
kss
,
err
:=
newKeyshareServer
(
managerID
,
manager
.
KeyshareServer
)
if
err
!=
nil
{
return
err
}
message
:=
keyshareEnrollment
{
Email
:
email
,
Pin
:
kss
.
HashedPin
(
pin
),
Language
:
lang
,
PublicKey
:
(
*
paillierPublicKey
)(
&
kss
.
PrivateKey
.
PublicKey
),
Email
:
email
,
Pin
:
kss
.
HashedPin
(
pin
),
Language
:
lang
,
}
qr
:=
&
irma
.
Qr
{}
...
...
@@ -786,6 +748,22 @@ func (client *Client) keyshareEnrollWorker(managerID irma.SchemeManagerIdentifie
return
nil
}
// KeyshareVerifyPin verifies the specified PIN at the keyshare server, returning if it succeeded;
// if not, how many tries are left, or for how long the user is blocked. If an error is returned
// it is of type *irma.SessionError.
func
(
client
*
Client
)
KeyshareVerifyPin
(
pin
string
,
schemeid
irma
.
SchemeManagerIdentifier
)
(
bool
,
int
,
int
,
error
)
{
scheme
:=
client
.
Configuration
.
SchemeManagers
[
schemeid
]
if
scheme
==
nil
||
!
scheme
.
Distributed
()
{
return
false
,
0
,
0
,
&
irma
.
SessionError
{
Err
:
errors
.
Errorf
(
"Can't verify pin of scheme %s"
,
schemeid
.
String
()),
ErrorType
:
irma
.
ErrorUnknownSchemeManager
,
Info
:
schemeid
.
String
(),
}
}
kss
:=
client
.
keyshareServers
[
schemeid
]
return
verifyPinWorker
(
pin
,
kss
,
irma
.
NewHTTPTransport
(
kss
.
URL
))
}
func
(
client
*
Client
)
KeyshareChangePin
(
manager
irma
.
SchemeManagerIdentifier
,
oldPin
string
,
newPin
string
)
{
go
func
()
{
err
:=
client
.
keyshareChangePinWorker
(
manager
,
oldPin
,
newPin
)
...
...
irmaclient/irmaclient_test.go
View file @
db143b0b
...
...
@@ -3,12 +3,11 @@ package irmaclient
import
(
"encoding/json"
"errors"
gobig
"math/big"
"os"
"testing"
"github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/big"
"github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/fs"
"github.com/privacybydesign/irmago/internal/test"
...
...
@@ -80,33 +79,12 @@ func verifyCredentials(t *testing.T, client *Client) {
}
}
func
verifyPaillierKey
(
t
*
testing
.
T
,
PrivateKey
*
paillierPrivateKey
)
{
require
.
NotNil
(
t
,
PrivateKey
)
require
.
NotNil
(
t
,
PrivateKey
.
L
)
require
.
NotNil
(
t
,
PrivateKey
.
U
)
require
.
NotNil
(
t
,
PrivateKey
.
PublicKey
.
N
)
require
.
Equal
(
t
,
gobig
.
NewInt
(
1
),
new
(
gobig
.
Int
)
.
Exp
(
gobig
.
NewInt
(
2
),
PrivateKey
.
L
,
PrivateKey
.
N
))
require
.
Equal
(
t
,
PrivateKey
.
NSquared
,
new
(
gobig
.
Int
)
.
Exp
(
PrivateKey
.
N
,
gobig
.
NewInt
(
2
),
nil
))
plaintext
:=
"Hello Paillier!"
ciphertext
,
err
:=
PrivateKey
.
Encrypt
([]
byte
(
plaintext
))
require
.
NoError
(
t
,
err
)
decrypted
,
err
:=
PrivateKey
.
Decrypt
(
ciphertext
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
plaintext
,
string
(
decrypted
))
}
func
verifyKeyshareIsUnmarshaled
(
t
*
testing
.
T
,
client
*
Client
)
{
require
.
NotNil
(
t
,
client
.
paillierKeyCache
)
require
.
NotNil
(
t
,
client
.
keyshareServers
)
testManager
:=
irma
.
NewSchemeManagerIdentifier
(
"test"
)
require
.
Contains
(
t
,
client
.
keyshareServers
,
testManager
)
kss
:=
client
.
keyshareServers
[
testManager
]
require
.
NotEmpty
(
t
,
kss
.
Nonce
)
verifyPaillierKey
(
t
,
kss
.
PrivateKey
)
verifyPaillierKey
(
t
,
client
.
paillierKeyCache
)
}
func
TestStorageDeserialization
(
t
*
testing
.
T
)
{
...
...
@@ -184,36 +162,6 @@ func TestCandidates(t *testing.T) {
require
.
Empty
(
t
,
attrs
)
}
func
TestPaillier
(
t
*
testing
.
T
)
{
client
:=
parseStorage
(
t
)
defer
test
.
ClearTestStorage
(
t
)
challenge
,
_
:=
gabi
.
RandomBigInt
(
256
)
comm
,
_
:=
gabi
.
RandomBigInt
(
1000
)
resp
,
_
:=
gabi
.
RandomBigInt
(
1000
)
sk
:=
client
.
paillierKey
(
true
)
bytes
,
err
:=
sk
.
Encrypt
(
challenge
.
Bytes
())
require
.
NoError
(
t
,
err
)
cipher
:=
new
(
big
.
Int
)
.
SetBytes
(
bytes
)
bytes
,
err
=
sk
.
Encrypt
(
comm
.
Bytes
())
require
.
NoError
(
t
,
err
)
commcipher
:=
new
(
big
.
Int
)
.
SetBytes
(
bytes
)
// [[ c ]]^resp * [[ comm ]]
nsquared
:=
big
.
Convert
(
sk
.
NSquared
)
cipher
.
Exp
(
cipher
,
resp
,
nsquared
)
.
Mul
(
cipher
,
commcipher
)
.
Mod
(
cipher
,
nsquared
)
bytes
,
err
=
sk
.
Decrypt
(
cipher
.
Bytes
())
require
.
NoError
(
t
,
err
)
plaintext
:=
new
(
big
.
Int
)
.
SetBytes
(
bytes
)
expected
:=
new
(
big
.
Int
)
.
Set
(
challenge
)
expected
.
Mul
(
expected
,
resp
)
.
Add
(
expected
,
comm
)
require
.
Equal
(
t
,
plaintext
,
expected
)
}
func
TestCredentialRemoval
(
t
*
testing
.
T
)
{
client
:=
parseStorage
(
t
)
defer
test
.
ClearTestStorage
(
t
)
...
...
irmaclient/keyshare.go
View file @
db143b0b
...
...
@@ -52,20 +52,18 @@ type keyshareSession struct {
}
type
keyshareServer
struct
{
URL
string
`json:"url"`
Username
string
`json:"username"`
Nonce
[]
byte
`json:"nonce"`
PrivateKey
*
paillierPrivateKey
`json:"keyPair"`
URL
string
`json:"url"`
Username
string
`json:"username"`
Nonce
[]
byte
`json:"nonce"`
SchemeManagerIdentifier
irma
.
SchemeManagerIdentifier
token
string
}
type
keyshareEnrollment
struct
{
Username
string
`json:"username"`
Pin
string
`json:"pin"`
PublicKey
*
paillierPublicKey
`json:"publicKey"`
Email
*
string
`json:"email"`
Language
string
`json:"language"`
Username
string
`json:"username"`
Pin
string
`json:"pin"`
Email
*
string
`json:"email"`
Language
string
`json:"language"`
}
type
keyshareChangepin
struct
{
...
...
@@ -129,13 +127,11 @@ const (
func
newKeyshareServer
(
schemeManagerIdentifier
irma
.
SchemeManagerIdentifier
,
privatekey
*
paillierPrivateKey
,
url
string
,
)
(
ks
*
keyshareServer
,
err
error
)
{
ks
=
&
keyshareServer
{
Nonce
:
make
([]
byte
,
32
),
URL
:
url
,
PrivateKey
:
privatekey
,
Nonce
:
make
([]
byte
,
32
),
URL
:
url
,
SchemeManagerIdentifier
:
schemeManagerIdentifier
,
}
_
,
err
=
rand
.
Read
(
ks
.
Nonce
)
...
...
@@ -279,6 +275,37 @@ func (ks *keyshareSession) VerifyPin(attempts int) {
}))
}
func
verifyPinWorker
(
pin
string
,
kss
*
keyshareServer
,
transport
*
irma
.
HTTPTransport
)
(
success
bool
,
tries
int
,
blocked
int
,
err
error
)
{
pinmsg
:=
keysharePinMessage
{
Username
:
kss
.
Username
,
Pin
:
kss
.
HashedPin
(
pin
)}
pinresult
:=
&
keysharePinStatus
{}
err
=
transport
.
Post
(
"users/verify/pin"
,
pinresult
,
pinmsg
)
if
err
!=
nil
{
return
}
switch
pinresult
.
Status
{
case
kssPinSuccess
:
success
=
true
kss
.
token
=
pinresult
.
Message
transport
.
SetHeader
(
kssAuthHeader
,
kss
.
token
)
return
case
kssPinFailure
:
tries
,
err
=
strconv
.
Atoi
(
pinresult
.
Message
)
return
case
kssPinError
:
blocked
,
err
=
strconv
.
Atoi
(
pinresult
.
Message
)
return
default
:
err
=
&
irma
.
SessionError
{
Err
:
errors
.
New
(
"Keyshare server returned unrecognized PIN status"
),
ErrorType
:
irma
.
ErrorServerResponse
,
Info
:
"Keyshare server returned unrecognized PIN status"
,
}
return
}
}
// Verify the specified pin at each of the keyshare servers involved in the specified session.
// - If the pin did not verify at one of the keyshare servers but there are attempts remaining,
// the amount of remaining attempts is returned as the second return value.
...
...
@@ -296,30 +323,11 @@ func (ks *keyshareSession) verifyPinAttempt(pin string) (
kss
:=
ks
.
keyshareServers
[
manager
]
transport
:=
ks
.
transports
[
manager
]
pinmsg
:=
keysharePinMessage
{
Username
:
kss
.
Username
,
Pin
:
kss
.
HashedPin
(
pin
)}
pinresult
:=
&
keysharePinStatus
{}
err
=
transport
.
Post
(
"users/verify/pin"
,
pinresult
,
pinmsg
)
if
err
!=
nil
{
return
}
switch
pinresult
.
Status
{
case
kssPinSuccess
:
kss
.
token
=
pinresult
.
Message
transport
.
SetHeader
(
kssAuthHeader
,
"Bearer "
+
kss
.
token
)
case
kssPinFailure
:
tries
,
err
=
strconv
.
Atoi
(
pinresult
.
Message
)
return
case
kssPinError
:
blocked
,
err
=
strconv
.
Atoi
(
pinresult
.
Message
)
return
default
:
err
=
errors
.
New
(
"Keyshare server returned unrecognized PIN status"
)
success
,
tries
,
blocked
,
err
=
verifyPinWorker
(
pin
,
kss
,
transport
)
if
!
success
{
return
}
}
success
=
true
return
}
...
...
@@ -390,18 +398,7 @@ func (ks *keyshareSession) GetCommitments() {
// receive their responses (2nd and 3rd message in Schnorr zero-knowledge protocol).
func
(
ks
*
keyshareSession
)
GetProofPs
()
{
_
,
issig
:=
ks
.
session
.
(
*
irma
.
SignatureRequest
)
_
,
issuing
:=
ks
.
session
.
(
*
irma
.
IssuanceRequest
)
challenge
:=
ks
.
builders
.
Challenge
(
ks
.
session
.
GetContext
(),
ks
.
session
.
GetNonce
(),
issig
)
kssChallenge
:=
challenge
// In disclosure or signature sessions the challenge is Paillier encrypted.
if
!
issuing
{
bytes
,
err
:=
ks
.
keyshareServer
.
PrivateKey
.
Encrypt
(
challenge
.
Bytes
())
if
err
!=
nil
{
ks
.
sessionHandler
.
KeyshareError
(
&
ks
.
keyshareServer
.
SchemeManagerIdentifier
,
err
)
}
kssChallenge
=
new
(
big
.
Int
)
.
SetBytes
(
bytes
)
}
// Post the challenge, obtaining JWT's containing the ProofP's
responses
:=
map
[
irma
.
SchemeManagerIdentifier
]
string
{}
...
...
@@ -411,7 +408,7 @@ func (ks *keyshareSession) GetProofPs() {
continue
}
var
jwt
string
err
:=
transport
.
Post
(
"prove/getResponse"
,
&
jwt
,
kssC
hallenge
)
err
:=
transport
.
Post
(
"prove/getResponse"
,
&
jwt
,
c
hallenge
)
if
err
!=
nil
{
ks
.
sessionHandler
.
KeyshareError
(
&
managerID
,
err
)
return
...
...
@@ -465,15 +462,7 @@ func (ks *keyshareSession) finishDisclosureOrSigning(challenge *big.Int, respons
ks
.
sessionHandler
.
KeyshareError
(
&
managerID
,
err
)
return
}
// Decrypt the responses and populate a slice of ProofP's
proofPs
[
i
]
=
claims
.
ProofP
bytes
,
err
:=
ks
.
keyshareServer
.
PrivateKey
.
Decrypt
(
proofPs
[
i
]
.
SResponse
.
Bytes
())
if
err
!=
nil
{
ks
.
sessionHandler
.
KeyshareError
(
&
managerID
,
err
)
return
}
proofPs
[
i
]
.
SResponse
=
new
(
big
.
Int
)
.
SetBytes
(
bytes
)
}
// Create merged proofs and finish protocol
...
...
irmaclient/paillier.go
deleted
100644 → 0
View file @
2c58b9be
package
irmaclient
import
(
"encoding/json"
"math/big"
"github.com/credentials/go-go-gadget-paillier"
)
// paillierPrivateKey is an alias for paillier.PrivateKey so that we can add a custom unmarshaler to it.
type
paillierPrivateKey
paillier
.
PrivateKey
type
paillierPublicKey
paillier
.
PublicKey
func
(
psk
*
paillierPrivateKey
)
UnmarshalJSON
(
bytes
[]
byte
)
(
err
error
)
{
sk
:=
new
(
paillier
.
PrivateKey
)
if
err
=
json
.
Unmarshal
(
bytes
,
sk
);
err
!=
nil
{
return
}
*
psk
=
paillierPrivateKey
(
*
sk
)
return
}
func
(
psk
*
paillierPrivateKey
)
MarshalJSON
()
([]
byte
,
error
)
{
return
json
.
Marshal
(
paillier
.
PrivateKey
(
*
psk
))
}
func
(
psk
*
paillierPrivateKey
)
Encrypt
(
bytes
[]
byte
)
([]
byte
,
error
)
{
return
paillier
.
Encrypt
(
&
psk
.
PublicKey
,
bytes
)
}
func
(
psk
*
paillierPrivateKey
)
Decrypt
(
bytes
[]
byte
)
([]
byte
,
error
)
{
return
paillier
.
Decrypt
((
*
paillier
.
PrivateKey
)(
psk
),
bytes
)
}
func
(
ppk
*
paillierPublicKey
)
MarshalJSON
()
([]
byte
,
error
)
{
temp
:=
struct
{
N
*
big
.
Int
`json:"n"`
G
*
big
.
Int
`json:"g"`
NSquared
*
big
.
Int
`json:"nSquared"`
Bits
int
`json:"bits"`
}{
ppk
.
N
,
ppk
.
G
,
ppk
.
NSquared
,
ppk
.
N
.
BitLen
()}
return
json
.
Marshal
(
temp
)
}
irmaclient/storage.go
View file @
db143b0b
...
...
@@ -24,7 +24,6 @@ const (
skFile
=
"sk"
attributesFile
=
"attrs"
kssFile
=
"kss"
paillierFile
=
"paillier"
updatesFile
=
"updates"
logsFile
=
"logs"
preferencesFile
=
"preferences"
...
...
@@ -103,10 +102,6 @@ func (s *storage) StoreKeyshareServers(keyshareServers map[irma.SchemeManagerIde
return
s
.
store
(
keyshareServers
,
kssFile
)
}
func
(
s
*
storage
)
StorePaillierKeys
(
key
*
paillierPrivateKey
)
error
{
return
s
.
store
(
key
,
paillierFile
)
}
func
(
s
*
storage
)
StoreLogs
(
logs
[]
*
LogEntry
)
error
{
return
s
.
store
(
logs
,
logsFile
)
}
...
...
@@ -184,17 +179,6 @@ func (s *storage) LoadKeyshareServers() (ksses map[irma.SchemeManagerIdentifier]
return
ksses
,
nil
}
func
(
s
*
storage
)
LoadPaillierKeys
()
(
key
*
paillierPrivateKey
,
err
error
)
{
key
=
new
(
paillierPrivateKey
)
if
err
:=
s
.
load
(
key
,
paillierFile
);
err
!=
nil
{
return
nil
,
err
}
if
key
.
N
==
nil
{
// TODO this is ugly
return
nil
,
nil
}
return
key
,
nil
}
func
(
s
*
storage
)
LoadLogs
()
(
logs
[]
*
LogEntry
,
err
error
)
{
logs
=
[]
*
LogEntry
{}
if
err
:=
s
.
load
(
&
logs
,
logsFile
);
err
!=
nil
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment