Commit 40ff4726 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

refactor: rename structs, interfaces, members, vars and more of the keyshare server

parent 66771bd7
...@@ -16,17 +16,20 @@ const ( ...@@ -16,17 +16,20 @@ const (
) )
type ( type (
AesKey [32]byte AESKey [32]byte
Core struct { Core struct {
// Keys used for storage encryption/decryption // Keys used for storage encryption/decryption
decryptionKeys map[uint32]AesKey decryptionKeys map[uint32]AESKey
encryptionKey AesKey decryptionKey AESKey
encryptionKeyID uint32 decryptionKeyID uint32
// Key used to sign keyshare protocol messages // Key used to sign keyshare protocol messages
signKey *rsa.PrivateKey jwtPrivateKey *rsa.PrivateKey
signKeyID uint32 jwtPrivateKeyID uint32
jwtIssuer string
jwtPinExpiry int
// Commit values generated in first step of keyshare protocol // Commit values generated in first step of keyshare protocol
commitmentData map[uint64]*big.Int commitmentData map[uint64]*big.Int
...@@ -35,16 +38,17 @@ type ( ...@@ -35,16 +38,17 @@ type (
// IRMA issuer keys that are allowed to be used in keyshare // IRMA issuer keys that are allowed to be used in keyshare
// sessions // sessions
trustedKeys map[irma.PublicKeyIdentifier]*gabikeys.PublicKey trustedKeys map[irma.PublicKeyIdentifier]*gabikeys.PublicKey
jwtIssuer string
jwtPinExpiry int
} }
Configuration struct { Configuration struct {
AESKeyID uint32 // Keys used for storage encryption/decryption
AESKey AesKey DecryptionKey AESKey
SignKeyID uint32 DecryptionKeyID uint32
SignKey *rsa.PrivateKey
// Key used to sign keyshare protocol messages
JWTPrivateKey *rsa.PrivateKey
JWTPrivateKeyID uint32
JWTIssuer string JWTIssuer string
JWTPinExpiry int // in seconds JWTPinExpiry int // in seconds
} }
...@@ -52,13 +56,13 @@ type ( ...@@ -52,13 +56,13 @@ type (
func NewKeyshareCore(conf *Configuration) *Core { func NewKeyshareCore(conf *Configuration) *Core {
c := &Core{ c := &Core{
decryptionKeys: map[uint32]AesKey{}, decryptionKeys: map[uint32]AESKey{},
commitmentData: map[uint64]*big.Int{}, commitmentData: map[uint64]*big.Int{},
trustedKeys: map[irma.PublicKeyIdentifier]*gabikeys.PublicKey{}, trustedKeys: map[irma.PublicKeyIdentifier]*gabikeys.PublicKey{},
} }
c.setAESEncryptionKey(conf.AESKeyID, conf.AESKey) c.setDecryptionKey(conf.DecryptionKeyID, conf.DecryptionKey)
c.setSignKey(conf.SignKeyID, conf.SignKey) c.setJWTPrivateKey(conf.JWTPrivateKeyID, conf.JWTPrivateKey)
c.jwtIssuer = conf.JWTIssuer c.jwtIssuer = conf.JWTIssuer
if c.jwtIssuer == "" { if c.jwtIssuer == "" {
...@@ -72,31 +76,31 @@ func NewKeyshareCore(conf *Configuration) *Core { ...@@ -72,31 +76,31 @@ func NewKeyshareCore(conf *Configuration) *Core {
return c return c
} }
func GenerateAESKey() (AesKey, error) { func GenerateDecryptionKey() (AESKey, error) {
var res AesKey var res AESKey
_, err := rand.Read(res[:]) _, err := rand.Read(res[:])
return res, err return res, err
} }
// Add an aes key for decryption, with identifier keyid // Add an aes key for decryption, with identifier keyid
// Calling this will cause all keyshare packets generated with the key to be trusted // Calling this will cause all keyshare packets generated with the key to be trusted
func (c *Core) DangerousAddAESKey(keyID uint32, key AesKey) { func (c *Core) DangerousAddDecryptionKey(keyID uint32, key AESKey) {
c.decryptionKeys[keyID] = key c.decryptionKeys[keyID] = key
} }
// Set the aes key for encrypting new/changed keyshare data // Set the aes key for encrypting new/changed keyshare data
// with identifier keyid // with identifier keyid
// Calling this wil also cause all keyshare packets generated with the key to be trusted // Calling this will also cause all keyshare packets generated with the key to be trusted
func (c *Core) setAESEncryptionKey(keyID uint32, key AesKey) { func (c *Core) setDecryptionKey(keyID uint32, key AESKey) {
c.decryptionKeys[keyID] = key c.decryptionKeys[keyID] = key
c.encryptionKey = key c.decryptionKey = key
c.encryptionKeyID = keyID c.decryptionKeyID = keyID
} }
// Set key used to sign keyshare protocol messages // Set key used to sign keyshare protocol messages
func (c *Core) setSignKey(id uint32, key *rsa.PrivateKey) { func (c *Core) setJWTPrivateKey(id uint32, key *rsa.PrivateKey) {
c.signKey = key c.jwtPrivateKey = key
c.signKeyID = id c.jwtPrivateKeyID = id
} }
// Add public key as trusted by keyshareCore. Calling this on incorrectly generated key material WILL compromise keyshare secrets! // Add public key as trusted by keyshareCore. Calling this on incorrectly generated key material WILL compromise keyshare secrets!
......
...@@ -26,43 +26,43 @@ var ( ...@@ -26,43 +26,43 @@ var (
) )
// Generate a new keyshare secret, secured with the given pin // Generate a new keyshare secret, secured with the given pin
func (c *Core) GenerateKeyshareSecret(pinRaw string) (EncryptedKeysharePacket, error) { func (c *Core) NewUser(pinRaw string) (User, error) {
secret, err := gabi.NewKeyshareSecret() secret, err := gabi.NewKeyshareSecret()
if err != nil { if err != nil {
return EncryptedKeysharePacket{}, err return User{}, err
} }
return c.DangerousBuildKeyshareSecret(pinRaw, secret) return c.newUserFromSecret(pinRaw, secret)
} }
func (c *Core) DangerousBuildKeyshareSecret(pinRaw string, secret *big.Int) (EncryptedKeysharePacket, error) { func (c *Core) newUserFromSecret(pinRaw string, secret *big.Int) (User, error) {
pin, err := padPin(pinRaw) pin, err := padPin(pinRaw)
if err != nil { if err != nil {
return EncryptedKeysharePacket{}, err return User{}, err
} }
var id [32]byte var id [32]byte
_, err = rand.Read(id[:]) _, err = rand.Read(id[:])
if err != nil { if err != nil {
return EncryptedKeysharePacket{}, err return User{}, err
} }
// Build unencrypted packet // Build unencrypted packet
var p unencryptedKeysharePacket var p unencryptedUser
p.setPin(pin) p.setPin(pin)
err = p.setKeyshareSecret(secret) err = p.setKeyshareSecret(secret)
if err != nil { if err != nil {
return EncryptedKeysharePacket{}, err return User{}, err
} }
p.setID(id) p.setID(id)
// And encrypt // And encrypt
return c.encryptPacket(p) return c.encryptUser(p)
} }
// Check pin for validity, and generate jwt for future access // Check pin for validity, and generate jwt for future access
func (c *Core) ValidatePin(ep EncryptedKeysharePacket, pin string, userID string) (string, error) { func (c *Core) ValidatePin(ep User, pin string, userID string) (string, error) {
p, err := c.decryptPacketIfPinOK(ep, pin) p, err := c.decryptUserIfPinOK(ep, pin)
if err != nil { if err != nil {
return "", err return "", err
} }
...@@ -76,88 +76,88 @@ func (c *Core) ValidatePin(ep EncryptedKeysharePacket, pin string, userID string ...@@ -76,88 +76,88 @@ func (c *Core) ValidatePin(ep EncryptedKeysharePacket, pin string, userID string
"exp": time.Now().Add(time.Duration(c.jwtPinExpiry) * time.Second).Unix(), "exp": time.Now().Add(time.Duration(c.jwtPinExpiry) * time.Second).Unix(),
"token_id": base64.StdEncoding.EncodeToString(id[:]), "token_id": base64.StdEncoding.EncodeToString(id[:]),
}) })
token.Header["kid"] = c.signKeyID token.Header["kid"] = c.jwtPrivateKeyID
return token.SignedString(c.signKey) return token.SignedString(c.jwtPrivateKey)
} }
// Check whether the given JWT is currently valid as an access token for operations on the provided encrypted keyshare packet // Check whether the given JWT is currently valid as an access token for operations on the provided encrypted keyshare packet
func (c *Core) ValidateJWT(ep EncryptedKeysharePacket, jwt string) error { func (c *Core) ValidateJWT(ep User, jwt string) error {
_, err := c.verifyAccess(ep, jwt) _, err := c.verifyAccess(ep, jwt)
return err return err
} }
// Change pin in an encrypted keyshare packet to a new value, after validating that the old value is known by caller. // Change pin in an encrypted keyshare packet to a new value, after validating that the old value is known by caller.
func (c *Core) ChangePin(ep EncryptedKeysharePacket, oldpinRaw, newpinRaw string) (EncryptedKeysharePacket, error) { func (c *Core) ChangePin(ep User, oldpinRaw, newpinRaw string) (User, error) {
p, err := c.decryptPacketIfPinOK(ep, oldpinRaw) p, err := c.decryptUserIfPinOK(ep, oldpinRaw)
if err != nil { if err != nil {
return EncryptedKeysharePacket{}, err return User{}, err
} }
newpin, err := padPin(newpinRaw) newpin, err := padPin(newpinRaw)
if err != nil { if err != nil {
return EncryptedKeysharePacket{}, err return User{}, err
} }
// change and reencrypt // change and reencrypt
var id [32]byte var id [32]byte
_, err = rand.Read(id[:]) _, err = rand.Read(id[:])
if err != nil { if err != nil {
return EncryptedKeysharePacket{}, err return User{}, err
} }
p.setPin(newpin) p.setPin(newpin)
p.setID(id) p.setID(id)
return c.encryptPacket(p) return c.encryptUser(p)
} }
// Verify that a given access jwt is valid, and if so, return decrypted keyshare packet // Verify that a given access jwt is valid, and if so, return decrypted keyshare packet
// Note: Although this is an internal function, it is tested directly // Note: Although this is an internal function, it is tested directly
func (c *Core) verifyAccess(ep EncryptedKeysharePacket, jwtToken string) (unencryptedKeysharePacket, error) { func (c *Core) verifyAccess(ep User, jwtToken string) (unencryptedUser, error) {
// Verify token validity // Verify token validity
token, err := jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) { token, err := jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) {
if token.Method != jwt.SigningMethodRS256 { if token.Method != jwt.SigningMethodRS256 {
return nil, ErrInvalidJWT return nil, ErrInvalidJWT
} }
return &c.signKey.PublicKey, nil return &c.jwtPrivateKey.PublicKey, nil
}) })
if err != nil { if err != nil {
return unencryptedKeysharePacket{}, ErrInvalidJWT return unencryptedUser{}, ErrInvalidJWT
} }
claims, ok := token.Claims.(jwt.MapClaims) claims, ok := token.Claims.(jwt.MapClaims)
if !ok || claims.Valid() != nil { if !ok || claims.Valid() != nil {
return unencryptedKeysharePacket{}, ErrInvalidJWT return unencryptedUser{}, ErrInvalidJWT
} }
if !claims.VerifyExpiresAt(time.Now().Unix(), true) { if !claims.VerifyExpiresAt(time.Now().Unix(), true) {
return unencryptedKeysharePacket{}, ErrInvalidJWT return unencryptedUser{}, ErrInvalidJWT
} }
if _, present := claims["token_id"]; !present { if _, present := claims["token_id"]; !present {
return unencryptedKeysharePacket{}, ErrInvalidJWT return unencryptedUser{}, ErrInvalidJWT
} }
tokenIDB64, ok := claims["token_id"].(string) tokenIDB64, ok := claims["token_id"].(string)
if !ok { if !ok {
return unencryptedKeysharePacket{}, ErrInvalidJWT return unencryptedUser{}, ErrInvalidJWT
} }
tokenID, err := base64.StdEncoding.DecodeString(tokenIDB64) tokenID, err := base64.StdEncoding.DecodeString(tokenIDB64)
if err != nil { if err != nil {
return unencryptedKeysharePacket{}, ErrInvalidJWT return unencryptedUser{}, ErrInvalidJWT
} }
p, err := c.decryptPacket(ep) p, err := c.decryptUser(ep)
if err != nil { if err != nil {
return unencryptedKeysharePacket{}, err return unencryptedUser{}, err
} }
refId := p.id() refId := p.id()
if subtle.ConstantTimeCompare(refId[:], tokenID) != 1 { if subtle.ConstantTimeCompare(refId[:], tokenID) != 1 {
return unencryptedKeysharePacket{}, ErrInvalidJWT return unencryptedUser{}, ErrInvalidJWT
} }
return p, nil return p, nil
} }
// Get keyshare commitment usign given idemix public key(s) // Get keyshare commitment usign given idemix public key(s)
func (c *Core) GenerateCommitments(ep EncryptedKeysharePacket, accessToken string, keyIDs []irma.PublicKeyIdentifier) ([]*gabi.ProofPCommitment, uint64, error) { func (c *Core) GenerateCommitments(ep User, accessToken string, keyIDs []irma.PublicKeyIdentifier) ([]*gabi.ProofPCommitment, uint64, error) {
// Validate input request and build key list // Validate input request and build key list
var keyList []*gabikeys.PublicKey var keyList []*gabikeys.PublicKey
for _, keyID := range keyIDs { for _, keyID := range keyIDs {
...@@ -196,7 +196,7 @@ func (c *Core) GenerateCommitments(ep EncryptedKeysharePacket, accessToken strin ...@@ -196,7 +196,7 @@ func (c *Core) GenerateCommitments(ep EncryptedKeysharePacket, accessToken strin
} }
// Generate response for zero-knowledge proof of keyshare secret, for a given previous commit and challenge // Generate response for zero-knowledge proof of keyshare secret, for a given previous commit and challenge
func (c *Core) GenerateResponse(ep EncryptedKeysharePacket, accessToken string, commitID uint64, challenge *big.Int, keyID irma.PublicKeyIdentifier) (string, error) { func (c *Core) GenerateResponse(ep User, accessToken string, commitID uint64, challenge *big.Int, keyID irma.PublicKeyIdentifier) (string, error) {
// Validate request // Validate request
if uint(challenge.BitLen()) > gabikeys.DefaultSystemParameters[1024].Lh || challenge.Cmp(big.NewInt(0)) < 0 { if uint(challenge.BitLen()) > gabikeys.DefaultSystemParameters[1024].Lh || challenge.Cmp(big.NewInt(0)) < 0 {
return "", ErrInvalidChallenge return "", ErrInvalidChallenge
...@@ -228,8 +228,8 @@ func (c *Core) GenerateResponse(ep EncryptedKeysharePacket, accessToken string, ...@@ -228,8 +228,8 @@ func (c *Core) GenerateResponse(ep EncryptedKeysharePacket, accessToken string,
"sub": "ProofP", "sub": "ProofP",
"iss": c.jwtIssuer, "iss": c.jwtIssuer,
}) })
token.Header["kid"] = c.signKeyID token.Header["kid"] = c.jwtPrivateKeyID
return token.SignedString(c.signKey) return token.SignedString(c.jwtPrivateKey)
} }
// Pad pin string into 64 bytes, extending it with 0s if neccessary // Pad pin string into 64 bytes, extending it with 0s if neccessary
......
...@@ -21,10 +21,10 @@ import ( ...@@ -21,10 +21,10 @@ import (
func TestPinFunctionality(t *testing.T) { func TestPinFunctionality(t *testing.T) {
// Setup keys for test // Setup keys for test
var key AesKey var key AESKey
_, err := rand.Read(key[:]) _, err := rand.Read(key[:])
require.NoError(t, err) require.NoError(t, err)
c := NewKeyshareCore(&Configuration{AESKeyID: 1, AESKey: key, SignKeyID: 1, SignKey: jwtTestKey}) c := NewKeyshareCore(&Configuration{DecryptionKeyID: 1, DecryptionKey: key, JWTPrivateKeyID: 1, JWTPrivateKey: jwtTestKey})
// generate test pin // generate test pin
var bpin [64]byte var bpin [64]byte
...@@ -33,7 +33,7 @@ func TestPinFunctionality(t *testing.T) { ...@@ -33,7 +33,7 @@ func TestPinFunctionality(t *testing.T) {
pin := string(bpin[:]) pin := string(bpin[:])
// Generate package // Generate package
ep, err := c.GenerateKeyshareSecret(pin) ep, err := c.NewUser(pin)
require.NoError(t, err) require.NoError(t, err)
// Test with correct pin // Test with correct pin
...@@ -67,10 +67,10 @@ func TestPinFunctionality(t *testing.T) { ...@@ -67,10 +67,10 @@ func TestPinFunctionality(t *testing.T) {
func TestVerifyAccess(t *testing.T) { func TestVerifyAccess(t *testing.T) {
// Setup keys for test // Setup keys for test
var key AesKey var key AESKey
_, err := rand.Read(key[:]) _, err := rand.Read(key[:])
require.NoError(t, err) require.NoError(t, err)
c := NewKeyshareCore(&Configuration{AESKeyID: 1, AESKey: key, SignKeyID: 1, SignKey: jwtTestKey}) c := NewKeyshareCore(&Configuration{DecryptionKeyID: 1, DecryptionKey: key, JWTPrivateKeyID: 1, JWTPrivateKey: jwtTestKey})
// Generate test pins // Generate test pins
var bpin [64]byte var bpin [64]byte
...@@ -82,9 +82,9 @@ func TestVerifyAccess(t *testing.T) { ...@@ -82,9 +82,9 @@ func TestVerifyAccess(t *testing.T) {
pin2 := string(bpin[:]) pin2 := string(bpin[:])
// and test keyshare secrets // and test keyshare secrets
ep1, err := c.GenerateKeyshareSecret(pin1) ep1, err := c.NewUser(pin1)
require.NoError(t, err) require.NoError(t, err)
ep2, err := c.GenerateKeyshareSecret(pin2) ep2, err := c.NewUser(pin2)
require.NoError(t, err) require.NoError(t, err)
// Test use jwt on wrong packet // Test use jwt on wrong packet
...@@ -105,7 +105,7 @@ func TestVerifyAccess(t *testing.T) { ...@@ -105,7 +105,7 @@ func TestVerifyAccess(t *testing.T) {
"exp": time.Now().Add(-3 * time.Minute).Unix(), "exp": time.Now().Add(-3 * time.Minute).Unix(),
"token_id": tokenID, "token_id": tokenID,
}) })
jwtt, err = token.SignedString(c.signKey) jwtt, err = token.SignedString(c.jwtPrivateKey)
require.NoError(t, err) require.NoError(t, err)
_, err = c.verifyAccess(ep1, jwtt) _, err = c.verifyAccess(ep1, jwtt)
assert.Error(t, err) assert.Error(t, err)
...@@ -115,7 +115,7 @@ func TestVerifyAccess(t *testing.T) { ...@@ -115,7 +115,7 @@ func TestVerifyAccess(t *testing.T) {
"iat": time.Now().Unix(), "iat": time.Now().Unix(),
"token_id": tokenID, "token_id": tokenID,
}) })
jwtt, err = token.SignedString(c.signKey) jwtt, err = token.SignedString(c.jwtPrivateKey)
require.NoError(t, err) require.NoError(t, err)
_, err = c.verifyAccess(ep1, jwtt) _, err = c.verifyAccess(ep1, jwtt)
assert.Error(t, err) assert.Error(t, err)
...@@ -126,7 +126,7 @@ func TestVerifyAccess(t *testing.T) { ...@@ -126,7 +126,7 @@ func TestVerifyAccess(t *testing.T) {
"exp": "test", "exp": "test",
"token_id": tokenID, "token_id": tokenID,
}) })
jwtt, err = token.SignedString(c.signKey) jwtt, err = token.SignedString(c.jwtPrivateKey)
require.NoError(t, err) require.NoError(t, err)
_, err = c.verifyAccess(ep1, jwtt) _, err = c.verifyAccess(ep1, jwtt)
assert.Error(t, err) assert.Error(t, err)
...@@ -136,7 +136,7 @@ func TestVerifyAccess(t *testing.T) { ...@@ -136,7 +136,7 @@ func TestVerifyAccess(t *testing.T) {
"iat": time.Now().Unix(), "iat": time.Now().Unix(),
"exp": time.Now().Add(3 * time.Minute).Unix(), "exp": time.Now().Add(3 * time.Minute).Unix(),
}) })
jwtt, err = token.SignedString(c.signKey) jwtt, err = token.SignedString(c.jwtPrivateKey)
require.NoError(t, err) require.NoError(t, err)
_, err = c.verifyAccess(ep1, jwtt) _, err = c.verifyAccess(ep1, jwtt)
assert.Error(t, err) assert.Error(t, err)
...@@ -147,7 +147,7 @@ func TestVerifyAccess(t *testing.T) { ...@@ -147,7 +147,7 @@ func TestVerifyAccess(t *testing.T) {
"exp": time.Now().Add(3 * time.Minute).Unix(), "exp": time.Now().Add(3 * time.Minute).Unix(),
"token_id": 7, "token_id": 7,
}) })
jwtt, err = token.SignedString(c.signKey) jwtt, err = token.SignedString(c.jwtPrivateKey)
require.NoError(t, err) require.NoError(t, err)
_, err = c.verifyAccess(ep1, jwtt) _, err = c.verifyAccess(ep1, jwtt)
assert.Error(t, err) assert.Error(t, err)
...@@ -166,10 +166,10 @@ func TestVerifyAccess(t *testing.T) { ...@@ -166,10 +166,10 @@ func TestVerifyAccess(t *testing.T) {
func TestProofFunctionality(t *testing.T) { func TestProofFunctionality(t *testing.T) {
// Setup keys for test // Setup keys for test
var key AesKey var key AESKey
_, err := rand.Read(key[:]) _, err := rand.Read(key[:])
require.NoError(t, err) require.NoError(t, err)
c := NewKeyshareCore(&Configuration{AESKeyID: 1, AESKey: key, SignKeyID: 1, SignKey: jwtTestKey}) c := NewKeyshareCore(&Configuration{DecryptionKeyID: 1, DecryptionKey: key, JWTPrivateKeyID: 1, JWTPrivateKey: jwtTestKey})
c.DangerousAddTrustedPublicKey(irma.PublicKeyIdentifier{Issuer: irma.NewIssuerIdentifier("test"), Counter: 1}, testPubK1) c.DangerousAddTrustedPublicKey(irma.PublicKeyIdentifier{Issuer: irma.NewIssuerIdentifier("test"), Counter: 1}, testPubK1)
// generate test pin // generate test pin
...@@ -179,7 +179,7 @@ func TestProofFunctionality(t *testing.T) { ...@@ -179,7 +179,7 @@ func TestProofFunctionality(t *testing.T) {
pin := string(bpin[:]) pin := string(bpin[:])
// generate keyshare secret // generate keyshare secret
ep, err := c.GenerateKeyshareSecret(pin) ep, err := c.NewUser(pin)
require.NoError(t, err) require.NoError(t, err)
// Validate pin // Validate pin
...@@ -201,7 +201,7 @@ func TestProofFunctionality(t *testing.T) { ...@@ -201,7 +201,7 @@ func TestProofFunctionality(t *testing.T) {
}{} }{}
fmt.Println(Rjwt) fmt.Println(Rjwt)
_, err = jwt.ParseWithClaims(Rjwt, claims, func(tok *jwt.Token) (interface{}, error) { _, err = jwt.ParseWithClaims(Rjwt, claims, func(tok *jwt.Token) (interface{}, error) {
return &c.signKey.PublicKey, nil return &c.jwtPrivateKey.PublicKey, nil
}) })
require.NoError(t, err) require.NoError(t, err)
...@@ -216,10 +216,10 @@ func TestProofFunctionality(t *testing.T) { ...@@ -216,10 +216,10 @@ func TestProofFunctionality(t *testing.T) {