Accounts in Stellar are identified by a cryptographic key pair.
The public key, also known as the account id, can safely be shared with anybody. It is 52 characters long and begins with a
The private key, referred to as the secret seed, should be kept private & secure. It is also 52 characters long, but begins with an
For example, the following is a randomly generated account key pair. (This is an example only, do not use this.)
Account id: GD2HMF3BKITMXISCPTU7VVTFXDY5WSQK4QNIUATNCXVKBNWZP7FWZOXG Secret Seed: SDHXK2UNHTXVW2MZSOVOPYUKVXD3PEVKMNQZZGPODQMR67YTKWMOC732
The knowledge of a key pair does not imply that the account exists on any Stellar network. In other words, when you call
KeyPair.random, this does not create an account. To do that, you need to issue a transaction that contains a
CreateAccountOperation, as explained in Transacting.
There are actually two kinds of
KeyPair objects in the SDK.
- represents the public and secret components, and can be used for operations that require proof of the secret portion, such as transaction signing.
- represents only the public component. This is used to refer to accounts other than your own, such as the counterparty of a payment.
As the account id can be derived from the secret seed, there is no object which models the secret seed without the account id.
The SDK provides several ways to create or resolve
KeyPair is generated when you call
The chance of receiving a key pair that has been seen before is so miniscule that you might reasonably assume that any randomly generated pair is effectively unique.
If you know the secret seed (private key), then you can reconstitute the
// Provide the secret seed as a String val keyPair = KeyPair.fromSecretSeed( "SDHXK2UNHTXVW2MZSOVOPYUKVXD3PEVKMNQZZGPODQMR67YTKWMOC732") // or an Array[Char] KeyPair.fromSecretSeed( "SDHXK2UNHTXVW2MZSOVOPYUKVXD3PEVKMNQZZGPODQMR67YTKWMOC732".toCharArray.toIndexedSeq) // or a raw 32 byte seed KeyPair.fromSecretSeed( Hex.decodeHex("1123740522f11bfef6b3671f51e159ccf589ccf8965262dd5f97d1721d383dd4") )
If you only know the account id (public key), you can create the
val accountId = "GCXYKQF35XWATRB6AWDDV2Y322IFU2ACYYN5M2YB44IBWAIITQ4RYPXK" val publicKey = KeyPair.fromAccountId(accountId)
As a substitute for a valid secret seed, any passphrase can be used to deterministically derive a
As a convenience, accounts may also be identified by a human-readable address known as a Federated Address. These are in the format
Federated addresses can be resolved using the
fromAddress method. Because the actual public key is retrieved from the network, this method returns a
Future[PublicKey] and may fail.
That’s all you need to know about
KeyPairs. Continue reading to learn about how to inspect Stellar networks via Queries.
Keys can be restored from a mnemonic phrase and, optionally, a password.
val keyPair = KeyPair.fromMnemonicPhrase( phrase = "cable spray genius state float twenty onion head street palace net private " + "method loan turn phrase state blanket interest dry amazing dress blast tube", passphrase = "p4ssphr4se".getBytes("UTF-8")) keyPair.accountId mustEqual "GDAHPZ2NSYIIHZXM56Y36SBVTV5QKFIZGYMMBHOU53ETUSWTP62B63EQ"
Mnemonic phrases are available in Chinese (simplified & traditional), Czech, English, French, Italian, Japanese, Korean and Spanish. Additional languages can be implemented in clients as needed. See
val keyPair = KeyPair.fromMnemonicPhrase( phrase = "つぶす きそう かるい ようじ なまいき むさぼる あこがれる そっせん みせる しちょう " + "そんしつ まろやか しへい さわやか でんあつ めした せんとう だっきゃく ほっさ ひるやすみ " + "はさみ ようちえん おんだん えらい", wordList = JapaneseWords) keyPair.accountId mustEqual "GDEIRKSGFKJCCXUQAM2KVUOAFV626NESTZ5Q4FRCUXTTYHK6RTN66TY2"
You can construct a new random mnemonic phrase with any supported language and 128-256 bits of entropy.
val mnemonic = Mnemonic.random(SpanishWords, entropyBits = 128) val passphrase = new ByteString("perro salchicha".getBytes(UTF_8)) val keyPair = mnemonic.asRootKeyPair(passphrase) KeyPair.fromMnemonic(mnemonic, passphrase, SpanishWords).accountId mustEqual keyPair.accountId
(If you wish to use your own source of entropy, rather than rely on the JVM, you can do that via the method
Mnemonic phrases derive cryptographic seeds which are the the root of a vast tree of deterministic addresses. If you wish to do more than map a phrase to a
KeyPair, then you should access the
HDNode of the
Mnemonic. From any node, you can derive the child nodes to any depth.
val mnemonic = Mnemonic.random(FrenchWords) val passphrase = new ByteString("chien saucisse".getBytes(UTF_8)) val rootNode = mnemonic.asHDNode(passphrase) val node = rootNode.deriveChild(33, 18, 193, 4) node.privateKey mustEqual rootNode .deriveChild(33) .deriveChild(18) .deriveChild(193) .deriveChild(4) .privateKey
Note that the subtree of nodes
44/148/0 are dedicated to Stellar keys and can be accessed by the
KeyPair deriving methods on both