// KeyDeriv derives a key from k using opts. // The opts argument should be appropriate for the primitive used. func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error) { // Validate arguments if k == nil { return nil, errors.New("Invalid Key. It must not be nil.") } // Derive key switch k.(type) { case *ecdsaPrivateKey: // Validate opts if opts == nil { return nil, errors.New("Invalid Opts parameter. It must not be nil.") } ecdsaK := k.(*ecdsaPrivateKey) switch opts.(type) { // Re-randomized an ECDSA private key case *bccsp.ECDSAReRandKeyOpts: reRandOpts := opts.(*bccsp.ECDSAReRandKeyOpts) tempSK := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: ecdsaK.privKey.Curve, X: new(big.Int), Y: new(big.Int), }, D: new(big.Int), } var k = new(big.Int).SetBytes(reRandOpts.ExpansionValue()) var one = new(big.Int).SetInt64(1) n := new(big.Int).Sub(ecdsaK.privKey.Params().N, one) k.Mod(k, n) k.Add(k, one) tempSK.D.Add(ecdsaK.privKey.D, k) tempSK.D.Mod(tempSK.D, ecdsaK.privKey.PublicKey.Params().N) // Compute temporary public key tempX, tempY := ecdsaK.privKey.PublicKey.ScalarBaseMult(k.Bytes()) tempSK.PublicKey.X, tempSK.PublicKey.Y = tempSK.PublicKey.Add( ecdsaK.privKey.PublicKey.X, ecdsaK.privKey.PublicKey.Y, tempX, tempY, ) // 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.") } reRandomizedKey := &ecdsaPrivateKey{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 *aesPrivateKey: // Validate opts if opts == nil { return nil, errors.New("Invalid Opts parameter. It must not be nil.") } aesK := k.(*aesPrivateKey) switch opts.(type) { case *bccsp.HMACTruncated256AESDeriveKeyOpts: hmacOpts := opts.(*bccsp.HMACTruncated256AESDeriveKeyOpts) mac := hmac.New(csp.conf.hashFunction, aesK.privKey) mac.Write(hmacOpts.Argument()) hmacedKey := &aesPrivateKey{mac.Sum(nil)[:csp.conf.aesBitLength], false} // If the key is not Ephemeral, store it. if !opts.Ephemeral() { // Store the key err = csp.ks.StoreKey(hmacedKey) if err != nil { return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err) } } return hmacedKey, nil case *bccsp.HMACDeriveKeyOpts: hmacOpts := opts.(*bccsp.HMACDeriveKeyOpts) mac := hmac.New(csp.conf.hashFunction, aesK.privKey) mac.Write(hmacOpts.Argument()) hmacedKey := &aesPrivateKey{mac.Sum(nil), true} // If the key is not Ephemeral, store it. if !opts.Ephemeral() { // Store the key err = csp.ks.StoreKey(hmacedKey) if err != nil { return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err) } } return hmacedKey, nil default: return nil, fmt.Errorf("Unrecognized KeyDerivOpts provided [%s]", opts.Algorithm()) } default: return nil, fmt.Errorf("Key type not recognized [%s]", k) } }