# Key pairs

> Create and manage Ed25519, Secp256k1, and Secp256r1 keypairs for Sui transaction signing.

The Sui TypeScript SDK provides `Keypair` classes that handle logic for signing and verification
using the cryptographic key pairs associated with a Sui address.

The Sui TypeScript SDK supports three signing schemes:

| Sign scheme     | Class name         | Import folder                    |
| --------------- | ------------------ | -------------------------------- |
| Ed25519         | `Ed25519Keypair`   | `@mysten/sui/keypairs/ed25519`   |
| ECDSA Secp256k1 | `Secp256k1Keypair` | `@mysten/sui/keypairs/secp256k1` |
| ECDSA Secp256r1 | `Secp256r1Keypair` | `@mysten/sui/keypairs/secp256r1` |

For information on these schemes, see the
[Signatures](https://docs.sui.io/concepts/cryptography/transaction-auth/signatures) topic.

To use, import the key pair class your project uses from the `@mysten/sui/keypairs` folder. For
example, to use the Ed25519 scheme, import the `Ed25519Keypair` class from
`@mysten/sui/keypairs/ed25519`.

```typescript

```

To create a random key pair (which identifies a Sui address), instantiate a new `Keypair` class. To
reference a key pair from an existing secret key, pass the secret to the `fromSecretKey` function.

```typescript
// random Keypair
const keypair = new Ed25519Keypair();
// Keypair from an existing secret key (Uint8Array)
const keypair = Ed25519Keypair.fromSecretKey(secretKey);
```

With your key pair created, you can reference it when performing actions on the network. For
example, you can use it to sign transactions, like the following code that creates and signs a
personal message using the public key from the key pair created in the previous code:

```typescript
const publicKey = keypair.getPublicKey();
const message = new TextEncoder().encode('hello world');

const { signature } = await keypair.signPersonalMessage(message);
const isValid = await publicKey.verifyPersonalMessage(message, signature);
```

## Public keys

Each `Keypair` has an associated `PublicKey` class. You use the public key to verify signatures or
to retrieve its associated Sui address. You can access a `Keypair` from its `PublicKey` or construct
it from the bytes (as a `Uint8Array`) of the `PublicKey`, as in the following code:

```typescript

const keypair = new Ed25519Keypair();

// method 1
const bytes = keypair.getPublicKey().toRawBytes();
const publicKey = new Ed25519PublicKey(bytes);
const address = publicKey.toSuiAddress();

// method 2
const address = keypair.getPublicKey().toSuiAddress();
// or use `toSuiAddress()` directly
const address = keypair.toSuiAddress();
```

## Verifying signatures without a key pair

When you have an existing public key, you can use it to verify a signature. Verification ensures the
signature is valid for the provided message and is signed with the appropriate secret key.

The following code creates a key pair in the Ed25519 scheme, creates and signs a message with it,
then verifies the message to retrieve the public key. The code then uses `toSuiAddress()` to check
if the address associated with the public key matches the address that the key pair defines.

```typescript

const keypair = new Ed25519Keypair();
const message = new TextEncoder().encode('hello world');
const { signature } = await keypair.signPersonalMessage(message);

const publicKey = await verifyPersonalMessageSignature(message, signature);

if (!publicKey.verifyAddress(keypair.toSuiAddress())) {
	throw new Error('Signature was valid, but was signed by a different key pair');
}
```

## Verifying that a signature is valid for a specific address

`verifyPersonalMessageSignature` and `verifyTransactionSignature` accept an optional `address`, and
will throw an error if the signature is not valid for the provided address.

```typescript

const keypair = new Ed25519Keypair();
const message = new TextEncoder().encode('hello world');
const { signature } = await keypair.signPersonalMessage(message);

await verifyPersonalMessageSignature(message, signature, {
	address: keypair.toSuiAddress(),
});
```

## Verifying transaction signatures

Verifying transaction signatures is similar to personal message signature verification, except you
use `verifyTransactionSignature`:

```typescript
// import SuiGrpcClient to create a network client

// create a client connected to testnet
const client = new SuiGrpcClient({
	network: 'testnet',
	baseUrl: 'https://fullnode.testnet.sui.io:443',
});
const tx = new Transaction();
// ... add some transactions...
const bytes = await tx.build({ client });

const keypair = new Ed25519Keypair();
const { signature } = await keypair.signTransaction(bytes);

await verifyTransactionSignature(bytes, signature, {
	// optionally verify that the signature is valid for a specific address
	address: keypair.toSuiAddress(),
});
```

## Verifying zkLogin signatures

ZkLogin signatures can't be verified purely on the client. When verifying a zkLogin signature, the
SDK uses the GraphQL API to verify the signature. This works for Mainnet signatures without any
additional configuration.

For Testnet signatures, you need to provide a Testnet GraphQL Client:

```typescript

const publicKey = await verifyPersonalMessageSignature(message, zkSignature, {
	client: new SuiGraphQLClient({
		url: 'https://graphql.testnet.sui.io/graphql',
	}),
});
```

For some zklogin accounts, there are two valid addresses for a given set of inputs. This means you
might run into issues if you try to compare the address returned by `publicKey.toSuiAddress()`
directly with an expected address.

Instead, you can either pass in the expected address during verification, or use the
`publicKey.verifyAddress(address)` method:

```typescript

const publicKey = await verifyPersonalMessageSignature(message, zkSignature, {
	client: new SuiGraphQLClient({
		url: 'https://graphql.testnet.sui.io/graphql',
	}),
	// Pass in the expected address, and the verification method will throw an error if the signature is not valid for the provided address
	address: '0x...expectedAddress',
});
// or

if (!publicKey.verifyAddress('0x...expectedAddress')) {
	throw new Error('Signature was valid, but was signed by a different key pair');
}
```

Both of these methods will check the signature against both the standard and
[legacy versions of the zklogin address](https://sdk.mystenlabs.com/sui/zklogin#legacy-addresses).

## Deriving a key pair from a mnemonic

The Sui TypeScript SDK supports deriving a key pair from a mnemonic phrase. This can be useful when
building wallets or other tools that allow a user to import their private keys.

```typescript
const exampleMnemonic = 'result crisp session latin ...';

const keyPair = Ed25519Keypair.deriveKeypair(exampleMnemonic);
```

## Deriving a `Keypair` from a Bech32 encoded secret key

If you know the Keypair scheme for your secret key, you can use the `fromSecretKey` method of the
appropriate `Keypair` class to derive the keypair from the secret key.

```typescript

// Example bech32 encoded secret key (which always starts with 'suiprivkey')
const secretKey = 'suiprivkey1qzse89atw7d3zum8ujep76d2cxmgduyuast0y9fu23xcl0mpafgkktllhyc';

const keypair = Ed25519Keypair.fromSecretKey(secretKey);
```

You can also use the `decodeSuiPrivateKey` function to decode the secret key and determine the
keyScheme, and get the keypairs private key bytes, which can be used to instantiate the appropriate
`Keypair` class.

```typescript

const { scheme, secretKey } = decodeSuiPrivateKey(encoded);

// use scheme to choose the correct key pair
switch (scheme) {
	case 'ED25519':
		keypair = Ed25519Keypair.fromSecretKey(secretKey);
		break;
	case 'Secp256r1':
		keypair = Secp256r1Keypair.fromSecretKey(secretKey);
		break;
	case 'Secp256k1':
		keypair = Secp256k1Keypair.fromSecretKey(secretKey);
		break;
	default:
		throw new Error(`Unsupported key pair scheme: ${scheme}`);
}
```

See [SIP-15](https://github.com/sui-foundation/sips/blob/main/sips/sip-15.md) for additional context
and motivation.

If you know your keypair scheme, you can use the `fromSecretKey` method of the appropriate keypair
to directly derive the keypair from the secret key.

```typescript
const secretKey = 'suiprivkey1qzse89atw7d3zum8ujep76d2cxmgduyuast0y9fu23xcl0mpafgkktllhyc';

const keypair = Ed25519Keypair.fromSecretKey(secretKey);
```

You can also export a keypair to a Bech32 encoded secret key using the `getSecretKey` method.

```typescript
const secretKey = keypair.getSecretKey();
```

If you have only the raw private key bytes for your keypair, you can encode to the Bech32 format
using the `encodeSuiPrivateKey` function.

```typescript

const encoded = encodeSuiPrivateKey(
	new Uint8Array([
		59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253, 102,
		39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
	]),
	'ED25519',
);
```

## Deriving a `Keypair` from a hex encoded secret key

If you have an existing secret key formatted as a hex encoded string, you can derive a `Keypair` by
converting the secret key to a `Uint8Array` and passing it to the `fromSecretKey` method of a
`Keypair` class.

```typescript

const secret = '0x...';
const keypair = Ed25519Keypair.fromSecretKey(fromHex(secret));
```