Skip to content

Commit

Permalink
KeyDerive should accept ECC Public Key
Browse files Browse the repository at this point in the history
This changeset extends the KeyDrive() function so that it also supports
ECDSA Public Key "re-randomization".

Added unit-tests to cover and verify the various cases.

Change-Id: Ib48f6b34d928b5f79e9ac670829e5fe6273a2df1
Signed-off-by: Volodymyr Paprotski <vpaprots@ca.ibm.com>
  • Loading branch information
Volodymyr Paprotski committed Jan 18, 2017
1 parent 75a4c82 commit f04741e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 4 deletions.
57 changes: 56 additions & 1 deletion bccsp/sw/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,61 @@ func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, e

// Derive key
switch k.(type) {
case *ecdsaPublicKey:
// Validate opts
if opts == nil {
return nil, errors.New("Invalid Opts parameter. It must not be nil.")
}

ecdsaK := k.(*ecdsaPublicKey)

switch opts.(type) {

// Re-randomized an ECDSA private key
case *bccsp.ECDSAReRandKeyOpts:
reRandOpts := opts.(*bccsp.ECDSAReRandKeyOpts)
tempSK := &ecdsa.PublicKey{
Curve: ecdsaK.pubKey.Curve,
X: new(big.Int),
Y: new(big.Int),
}

var k = new(big.Int).SetBytes(reRandOpts.ExpansionValue())
var one = new(big.Int).SetInt64(1)
n := new(big.Int).Sub(ecdsaK.pubKey.Params().N, one)
k.Mod(k, n)
k.Add(k, one)

// Compute temporary public key
tempX, tempY := ecdsaK.pubKey.ScalarBaseMult(k.Bytes())
tempSK.X, tempSK.Y = tempSK.Add(
ecdsaK.pubKey.X, ecdsaK.pubKey.Y,
tempX, tempY,
)

// Verify temporary public key is a valid point on the reference curve
isOn := tempSK.Curve.IsOnCurve(tempSK.X, tempSK.Y)
if !isOn {
return nil, errors.New("Failed temporary public key IsOnCurve check.")
}

reRandomizedKey := &ecdsaPublicKey{tempSK}

// If the key is not Ephemeral, store it.
if !opts.Ephemeral() {
// Store the key
err = csp.ks.StoreKey(reRandomizedKey)
if err != nil {
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
}
}

return reRandomizedKey, nil

default:
return nil, fmt.Errorf("Unrecognized KeyDerivOpts provided [%s]", opts.Algorithm())

}
case *ecdsaPrivateKey:
// Validate opts
if opts == nil {
Expand Down Expand Up @@ -268,7 +323,7 @@ func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, e
// Verify temporary public key is a valid point on the reference curve
isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y)
if !isOn {
return nil, errors.New("Failed temporary public key IsOnCurve check. This is an foreign key.")
return nil, errors.New("Failed temporary public key IsOnCurve check.")
}

reRandomizedKey := &ecdsaPrivateKey{tempSK}
Expand Down
30 changes: 27 additions & 3 deletions bccsp/sw/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,20 +589,44 @@ func TestECDSAKeyReRand(t *testing.T) {
if err != nil {
t.Fatalf("Failed generating ECDSA key [%s]", err)
}
if k == nil {
t.Fatal("Failed re-randomizing ECDSA key. Re-randomized Key must be different from nil")
}

reRandomizedKey, err := currentBCCSP.KeyDeriv(k, &bccsp.ECDSAReRandKeyOpts{Temporary: false, Expansion: []byte{1}})
if err != nil {
t.Fatalf("Failed re-randomizing ECDSA key [%s]", err)
}
if k == nil {
t.Fatal("Failed re-randomizing ECDSA key. Re-randomized Key must be different from nil")
}
if !reRandomizedKey.Private() {
t.Fatal("Failed re-randomizing ECDSA key. Re-randomized Key should be private")
}
if reRandomizedKey.Symmetric() {
t.Fatal("Failed re-randomizing ECDSA key. Re-randomized Key should be asymmetric")
}

k2, err := k.PublicKey()
if err != nil {
t.Fatalf("Failed getting public ECDSA key from private [%s]", err)
}
if k2 == nil {
t.Fatal("Failed re-randomizing ECDSA key. Re-randomized Key must be different from nil")
}

reRandomizedKey2, err := currentBCCSP.KeyDeriv(k2, &bccsp.ECDSAReRandKeyOpts{Temporary: false, Expansion: []byte{1}})
if err != nil {
t.Fatalf("Failed re-randomizing ECDSA key [%s]", err)
}

if reRandomizedKey2.Private() {
t.Fatal("Re-randomized public Key must remain public")
}
if reRandomizedKey2.Symmetric() {
t.Fatal("Re-randomized ECDSA asymmetric key must remain asymmetric")
}

if false == bytes.Equal(reRandomizedKey.SKI(), reRandomizedKey2.SKI()) {
t.Fatal("Re-randomized ECDSA Private- or Public-Keys must end up having the same SKI")
}
}

func TestECDSASign(t *testing.T) {
Expand Down

0 comments on commit f04741e

Please sign in to comment.