Skip to content

Commit

Permalink
ts-sdk: add secp256k1 keypair
Browse files Browse the repository at this point in the history
  • Loading branch information
joyqvq committed Sep 6, 2022
1 parent 89dfa56 commit fcf29a4
Show file tree
Hide file tree
Showing 16 changed files with 604 additions and 127 deletions.
8 changes: 4 additions & 4 deletions crates/sui/src/keytool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,16 @@ impl KeyToolCommand {
}
KeyToolCommand::List => {
println!(
" {0: ^42} | {1: ^45} | {2: ^1}",
"Sui Address", "Public Key (Base64)", "Flag"
" {0: ^42} | {1: ^45} | {2: ^6}",
"Sui Address", "Public Key (Base64)", "Scheme"
);
println!("{}", ["-"; 100].join(""));
for pub_key in keystore.keys() {
println!(
" {0: ^42} | {1: ^45} | {2: ^1}",
" {0: ^42} | {1: ^45} | {2: ^6}",
Into::<SuiAddress>::into(&pub_key),
Base64::encode(&pub_key),
pub_key.flag()
pub_key.scheme().to_string()
);
}
}
Expand Down
12 changes: 12 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 23 additions & 1 deletion sdk/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ You can view the generated [Type Doc](https://typedoc.org/) for the [current rel

For the latest docs for the `main` branch, run `pnpm doc` and open the [doc/index.html](doc/index.html) in your browser.

## Testing

```
cd sdk/typescript
pnpm run test
```

## Usage

The `JsonRpcProvider` class provides a connection to the JSON-RPC Server and should be used for all read-only operations. The default URLs to connect with the RPC server are:
Expand Down Expand Up @@ -76,8 +83,9 @@ To transfer a `0x2::coin::Coin<SUI>`:

```typescript
import { Ed25519Keypair, JsonRpcProvider, RawSigner } from '@mysten/sui.js';
// Generate a new Keypair
// Generate a new Ed25519 Keypair
const keypair = new Ed25519Keypair();

const signer = new RawSigner(
keypair,
new JsonRpcProvider('https://gateway.devnet.sui.io:443')
Expand Down Expand Up @@ -174,3 +182,17 @@ const publishTxn = await signer.publish(
);
console.log('publishTxn', publishTxn);
```


Alternatively, a Secp256k1 can be initiated:

```typescript
import { Secp256k1Keypair, JsonRpcProvider, RawSigner } from '@mysten/sui.js';
// Generate a new Secp256k1 Keypair
const keypair = new Secp256k1Keypair();

const signer = new RawSigner(
keypair,
new JsonRpcProvider('https://gateway.devnet.sui.io:443')
);
```
2 changes: 2 additions & 0 deletions sdk/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@
},
"dependencies": {
"@mysten/bcs": "workspace:*",
"@noble/hashes": "^1.1.2",
"@noble/secp256k1": "^1.6.3",
"bn.js": "^5.2.0",
"buffer": "^6.0.3",
"cross-fetch": "^3.1.5",
Expand Down
28 changes: 18 additions & 10 deletions sdk/typescript/src/cryptography/ed25519-keypair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import nacl from 'tweetnacl';
import { Base64DataBuffer } from '../serialization/base64';
import { Keypair } from './keypair';
import { PublicKey } from './publickey';
import { Ed25519PublicKey } from './ed25519-publickey';
import { SignatureScheme } from './publickey';

/**
* Ed25519 Keypair data
Expand All @@ -21,10 +22,10 @@ export class Ed25519Keypair implements Keypair {
private keypair: Ed25519KeypairData;

/**
* Create a new keypair instance.
* Create a new Ed25519 keypair instance.
* Generate random keypair if no {@link Ed25519Keypair} is provided.
*
* @param keypair ed25519 keypair
* @param keypair Ed25519 keypair
*/
constructor(keypair?: Ed25519KeypairData) {
if (keypair) {
Expand All @@ -33,16 +34,23 @@ export class Ed25519Keypair implements Keypair {
this.keypair = nacl.sign.keyPair();
}
}

/**
* Get the key scheme of the keypair ED25519
*/
getKeyScheme(): SignatureScheme {
return 'ED25519';
}

/**
* Generate a new random keypair
* Generate a new random Ed25519 keypair
*/
static generate(): Ed25519Keypair {
return new Ed25519Keypair(nacl.sign.keyPair());
}

/**
* Create a keypair from a raw secret key byte array.
* Create a Ed25519 keypair from a raw secret key byte array.
*
* This method should only be used to recreate a keypair from a previously
* generated secret key. Generating keypairs from a random seed should be done
Expand Down Expand Up @@ -70,7 +78,7 @@ export class Ed25519Keypair implements Keypair {
}

/**
* Generate a keypair from a 32 byte seed.
* Generate a Ed25519 keypair from a 32 byte seed.
*
* @param seed seed byte array
*/
Expand All @@ -79,14 +87,14 @@ export class Ed25519Keypair implements Keypair {
}

/**
* The public key for this keypair
* The public key for this Ed25519 keypair
*/
getPublicKey(): PublicKey {
return new PublicKey(this.keypair.publicKey);
getPublicKey(): Ed25519PublicKey {
return new Ed25519PublicKey(this.keypair.publicKey);
}

/**
* Return the signature for the provided data.
* Return the signature for the provided data using Ed25519.
*/
signData(data: Base64DataBuffer): Base64DataBuffer {
return new Base64DataBuffer(
Expand Down
97 changes: 97 additions & 0 deletions sdk/typescript/src/cryptography/ed25519-publickey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import BN from 'bn.js';
import { Buffer } from 'buffer';
import { sha3_256 } from 'js-sha3';
import { checkPublicKeyData, PublicKeyInitData, SIGNATURE_SCHEME_TO_FLAG } from './publickey';

const PUBLIC_KEY_SIZE = 32;

/**
* An Ed25519 public key
*/
export class Ed25519PublicKey {
/** @internal */
_bn: BN;

/**
* Create a new Ed25519PublicKey object
* @param value ed25519 public key as buffer or base-64 encoded string
*/
constructor(value: PublicKeyInitData) {
if (checkPublicKeyData(value)) {
this._bn = value._bn;
} else {
if (typeof value === 'string') {
const buffer = Buffer.from(value, 'base64');
if (buffer.length !== PUBLIC_KEY_SIZE) {
throw new Error(
`Invalid public key input. Expected ${PUBLIC_KEY_SIZE} bytes, got ${buffer.length}`
);
}
this._bn = new BN(buffer);
} else {
this._bn = new BN(value);
}
let length = this._bn.byteLength();
if (length != PUBLIC_KEY_SIZE) {
throw new Error(
`Invalid public key input. Expected ${PUBLIC_KEY_SIZE} bytes, got ${length}`
);
}
}
}

/**
* Checks if two Ed25519 public keys are equal
*/
equals(publicKey: Ed25519PublicKey): boolean {
return this._bn.eq(publicKey._bn);
}

/**
* Return the base-64 representation of the Ed25519 public key
*/
toBase64(): string {
return this.toBuffer().toString('base64');
}

/**
* Return the byte array representation of the Ed25519 public key
*/
toBytes(): Uint8Array {
return this.toBuffer();
}

/**
* Return the Buffer representation of the Ed25519 public key
*/
toBuffer(): Buffer {
const b = this._bn.toArrayLike(Buffer);
if (b.length === PUBLIC_KEY_SIZE) {
return b;
}

const zeroPad = Buffer.alloc(PUBLIC_KEY_SIZE);
b.copy(zeroPad, PUBLIC_KEY_SIZE - b.length);
return zeroPad;
}

/**
* Return the base-64 representation of the Ed25519 public key
*/
toString(): string {
return this.toBase64();
}

/**
* Return the Sui address associated with this Ed25519 public key
*/
toSuiAddress(): string {
let tmp = new Uint8Array(PUBLIC_KEY_SIZE + 1);
tmp.set([SIGNATURE_SCHEME_TO_FLAG['ED25519']]);
tmp.set(this.toBytes(), 1);
return sha3_256(tmp).slice(0, 40);
}
}
7 changes: 6 additions & 1 deletion sdk/typescript/src/cryptography/keypair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { Base64DataBuffer } from '../serialization/base64';
import { PublicKey } from './publickey';
import { PublicKey, SignatureScheme } from './publickey';

/**
* A keypair used for signing transactions.
Expand All @@ -17,4 +17,9 @@ export interface Keypair {
* Return the signature for the data
*/
signData(data: Base64DataBuffer): Base64DataBuffer;

/**
* Get the key scheme of the keypair: Secp256k1 or ED25519
*/
getKeyScheme(): SignatureScheme;
}
Loading

0 comments on commit fcf29a4

Please sign in to comment.