Skip to content

Commit 48e0bad

Browse files
docs: add example
1 parent cbda857 commit 48e0bad

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

  • programs/token-2022/zkencryption/examples/deriveKeys
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2021 github.com/gagliardetto
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Command deriveKeys shows how to deterministically derive the two key
16+
// materials used by the Token-2022 confidential-transfer extension from a
17+
// Solana signer: the ElGamal secret key and the AES (AeKey) key.
18+
//
19+
// This is the primary derivation path used by wallets: the same signer and
20+
// public seed always derive the same keys, so a user can recover their
21+
// confidential-transfer keys from their wallet alone, with nothing stored
22+
// on-chain or off-chain. The keys produced here are byte-for-byte identical
23+
// to those from the Rust solana-zk-sdk and the JS/WASM @solana/zk-sdk, given
24+
// the same signer and seed.
25+
package main
26+
27+
import (
28+
"encoding/hex"
29+
"fmt"
30+
31+
"github.com/gagliardetto/solana-go"
32+
"github.com/gagliardetto/solana-go/programs/token-2022/zkencryption"
33+
)
34+
35+
func main() {
36+
// In a real application this is the user's wallet key (or a hardware
37+
// wallet / remote signer implementing zkencryption.Signer). solana.PrivateKey
38+
// already satisfies the Signer interface. We use a fixed seed here only so
39+
// the example output is reproducible.
40+
wallet := solana.NewWallet().PrivateKey
41+
42+
// The public seed scopes the derived keys. For confidential transfers this
43+
// is conventionally the token account (ATA) address whose balance the keys
44+
// protect, so distinct accounts owned by the same wallet get distinct keys.
45+
tokenAccount := solana.NewWallet().PublicKey()
46+
publicSeed := tokenAccount.Bytes()
47+
48+
elgamal, err := zkencryption.ElGamalSecretKeyFromSigner(wallet, publicSeed)
49+
if err != nil {
50+
panic(err)
51+
}
52+
53+
aeKey, err := zkencryption.AeKeyFromSigner(wallet, publicSeed)
54+
if err != nil {
55+
panic(err)
56+
}
57+
58+
fmt.Println("wallet: ", wallet.PublicKey())
59+
fmt.Println("token account: ", tokenAccount)
60+
fmt.Println("ElGamal secret key:", hex.EncodeToString(elgamal[:]))
61+
fmt.Println("AeKey: ", hex.EncodeToString(aeKey[:]))
62+
63+
// Derivation is deterministic: signer + public seed always yield the same
64+
// keys, which is what lets a wallet recover them on demand.
65+
again, err := zkencryption.ElGamalSecretKeyFromSigner(wallet, publicSeed)
66+
if err != nil {
67+
panic(err)
68+
}
69+
fmt.Println("deterministic: ", elgamal == again)
70+
}

0 commit comments

Comments
 (0)