How to generate Stellar keys
Published: 2021-01-14 17:41:55

# What is a key pair? 
Stellar keys are used to authenticate and identify users on the network. Stellar accounts are uniquely identified by their *public key*, also known as *account id*. A Stellar account id is a string that starts with the letter `G`, this key is safe to share with others. Accounts are controlled using a *secret key seed*, a string starting with `S`, and they should never be shared with other people or applications. The secret key seed is used to derive the private key. A private key and a public key together are known as a *key pair*. The private key is used to sign operations that modify the Stellar account state on the ledger.

# Generate key pairs with one of the SDKs 
Now that we know what is a key pair and what it is used for, we can see how to generate it using four different SDKs.

## Javascript
The `stellar-base` package is officially maintained by the Stellar Development Foundation and [is available on npm](https://www.npmjs.com/package/stellar-base).

``` javascript
import { Keypair } from "stellar-base";

// Generate random key pair
Keypair.random();

// Generate key pair from secret
Keypair.fromSecret("SA6KO...PRET");

// Generate key pair from account id
Keypair.fromPublicKey("GBMZ...ZPJK");
```

## Rust
The `stellar-base` crate provides low-level Stellar types, including key pairs. You can fetch it directly from [crates.io](https://crates.io/crates/stellar-base). The Rust SDK provides a `KeyPair` type that contains both the private and public keys, and a `PublicKey` type that contains only the public key. With this API design, it’s impossible to accidentally sign a transaction with a key pair that was constructed from the public key only.

``` rust
use stellar_base::crypto::{KeyPair, PublicKey};

// Generate random key pair
KeyPair::random()?;

// Generate key pair from secret
KeyPair.from_secret_seed("SA6KO...PRET")?;

// Generate public key from account id
PublicKey::from_account_id("GBMZ...ZPJK")?;
```

## C#
The `dotnet-stellar-sdk` is a C\# library to interact witth the Stellar ecosystem. It can be used in any language that targets .NET Standard 2.0 or above.

``` csharp
using stellar_dotnet_sdk;

// Generate random key pair
KeyPair.Random();

// Generate key pair from secret
KeyPair.FromSecretSeed("SA6KO...PRET");

// Generate key pair from account id
KeyPair.FromAccountId("GBMZ...ZPJK");
```

## Python
The Python `stellar-sdk` is available on [PyPi](https://pypi.org/project/stellar-sdk/) and can be installed with `pip`.

``` python
from stellar_sdk import Keypair

# Generate random key pair
Keypair.random();

# Generate key pair from secret
Keypair.from_secret("SA6KO...PRET");

# Generate key pair from account id
Keypair.from_public_key("GBMZ...ZPJK");
```

# What’s happening behind the scenes? 
Stellar uses the [EdDSA](https://tools.ietf.org/html/rfc8032) signature scheme for its transactions. A private key starts its life as a 32 bytes seed that is then used to generate the private key itself. The public key can be derived from the private key or created directly from a buffer of 32 bytes. I’m not going into too much detail how the private and public keys are derived, if you’re interested you can find more in [this excellent blog post by Brian Warner](https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/).

Going from a Stellar account id to a public key is very simple, you start by decoding the account id (a string starting with `G`) as *base32* and obtaining a buffer of 35 bytes. The first byte contains information about the type of key (secret seed, account id, pre-authorized transaction, or `hash(x)`), the next 32 bytes contain the key itself (or the secret key seed), finally the last 2 bytes contain the key checksum. Stellar uses [CRC-16 XMODEM](http://mdfs.net/Info/Comp/Comms/CRC16.htm) for the checksum of bytes 1 to 32.

![strkey-to-key](https://www.ceccon.me/images/strkey-to-key.png)

The process to compute a Stellar account id from a public key is similar, we concatenate the version byte with the public key bytes to obtain a 33 byte long payload. We then compute the 16 bit CRC of the payload. Finally, we concatenate the payload and its checksum and encode it using base32.