Yieldly Developer Series: Offline Deterministic Algorand Account Generator

Yieldly
8 min readDec 3, 2021

--

Background

Yieldly has built its reputation on the quality of our world-first DeFi and NFT products, as well as our trailblazing approach to complex technical work. We don’t outsource our services or solutions. Instead, we have an in-house team of world-class engineering and development specialists. Our team aims to deliver value not just to users and partners — but also to Algorand’s ever-growing developer community. That’s why we frequently make our innovative internal tools available to other developers in the ecosystem. In line with that, we have commenced a new blog series where we step through Yieldly’s developer tools and methods for problem-solving in the ecosystem.

It is a known issue that no simple offline solution to generating child keys exists on Algorand. Applications traditionally need to be connected to a running kmd client to generate wallets from a single seed phrase. To address this and simplify the process, our team did what we do best: we built our own while referencing the native implementation used by Algorand’s kmd service.

This allows the offline generation of child keys in a deterministic manner while still being backward compatible with both kmd and ledger.

How it works — A deeper understanding

For the tech-heads out there, let’s go in-depth on how our new tool works.

Each language package will have some minor differences between some functions, return values, and other variables; they more-or-less provide the same level of functionality which is shown in the “How to use (Examples)” section found later in this post.

Algorand’s Key Management Daemon (kmd) allows users to generate multiple wallet mnemonics from a single seed mnemonic similar to common BIP39 implementations. The kmd service utilises the ED25519 standard of encryption to generate the public and private keys of each account. For more information on the encryption method, please read this article from Algorand for more insight.

By utilising some standard encryption libraries, we are easily able to generate the public and private keys through a HKDF (HMAC Key Derivation Function) expansion. The required inputs to generate keys suitable for kmd includes a 32 byte long SHA512–256 truncated hash of your seed (traditionally known as a pseudo-random key) and some additional context (for more information on these params, read here). This seed is the derived master key of your wallet. You will commonly see this in its 25-word mnemonic form when first creating your wallet in kmd. This 25-word phrase is the BIP39 wordlist equivalent of the master key. This can be obtained by following the steps shown in the “How to use (Examples)” section.

Once you have public and private keys, you are now able to create the public addresses and mnemonics. However, some more work is needed to finalise the address to adhere to Algorand standards. A checksum is taken on both the public and private key separately, with the last 4 bytes of the public key checksum being appended and then base32 encoded to show the Algorand address in a format of which we are all most familiar. A similar process is done on the private key, where the first 2 bytes of the checksum are converted into 11-bit integers and the generated word appended to the derived 24-word mnemonic. (Link)

How to use (Examples)

BEFORE CONTINUING PLEASE READ THE DISCLAIMER

It is not recommended that you share your keys or mnemonics around. If anyone gets their hands on either your mnemonic or the derived master key, then they will be able to recreate the mnemonics / private keys of any account derived from the methods shown later in this document.

If you wish to test the compatibility with kmd, please refer to one of the following options to install algod + kmd to verify that the accounts you are generating are indeed deterministic.

Pull the code from the repository and open a terminal in the projects workspace. Examples for each programming language have been provided. Under the /src folder of the repository sits each respective programming languages folder. Due to the deliberate similarities of the software stack (every function has a mirrored version in terms of functionality on each programming language), choosing ultimately comes down to your preferred programming language.

You then proceed to /cd into your preferred languages folder and install all relevant packages.

Run the program file sitting under the /prog_language folder to get started. For example, with Python, this will be:

python3 main.py

You should then see a screen similar to the image below:

GENERATING MNEMONIC FROM DERIVATION MASTER KEY

Generate a new wallet like so (in this example, sandbox will be used):

Select yes to be able to see your wallet’s mnemonic, this will generate a 25 word sentence that you will need to note down somewhere. After obtaining your wallet’s mnemonic, run the program as described above and type “1” into the option selection.

You will then be asked to input your mnemonic phrase. Once you have entered all 25 words, press enter again, you should see your master key generated in base64 format in the output of the terminal.

GENERATING DERIVATION MASTER KEY FROM MNEMONIC

Select option 2:

Either by using the output generated from the above method or a key that you have managed to derive from another way, input your master key in base64 format. The console should then output your wallet’s mnemonic:

If you have used the method described under “GENERATING MNEMONIC FROM DERIVATION MASTER KEY” you should notice that the mnemonic that you entered is the same that was output in the console from this method. Showcasing that the system performs as expected and means you can freely call between the two functions.

GENERATING ACCOUNT ADDRESSES FROM EITHER DERIVATION MASTER KEY OR MNEMONIC

Select option 3:

You will then be asked to enter your mnemonic phrase or master key, followed by the index of where you would like to start. For a deeper look into how the accounts are generated, please go to the “How it works” section. For testing purposes, it is recommended that you start at index 1. Lastly, you will be prompted on how many accounts you would like to generate after this index. Please note that the maximum number of accounts that can be generated is 2⁶³ — 1.

If all your information is correct and in range, it should print a list of addresses as shown below:

If you have this wallet imported in your system, you should be able to generate the same addresses to verify that the program works.

GENERATING ACCOUNT MNEMONICS FROM EITHER DERIVATION MASTER KEY OR MNEMONIC

Select option 4. Similar to the above option, you will then be asked to enter your mnemonic phrase or master key, followed by the index of where you would like to start, for testing purposes, it is recommended that you start at index 1. Unlike generating account private keys, this example has been limited to producing 1 at a time. This is primarily for safety reasons for new users just wanting to learn how the system works without accidentally exposing every mnemonic in their wallet.

If all your information is correct and in range, it should print a mnemonic as shown below:

If you have this wallet imported in your system, you should be able to export the mnemonic to verify that both are equal and thus, verifies that the system can indeed deterministically generate accounts that are ready for use in the Algorand ecosystem.

Software Integration

BEFORE CONTINUING PLEASE READ THE DISCLAIMER

Feel free to pull the repository and utilise in any projects. Just ensure you have installed all the relevant packages included in each file and it should work as intended out of the box. For more information or examples on how to utilise them, please refer to “How to use (Examples).

Resources

Language Support

This software package currently supports the following languages:

· Typescript

· Go

· Python

File Structure

The basic shared structure of each programming languages folders is shown below:

-> /src

— — > /prog_language

— — — — > main_program.ext

— — — — > /utils

— — — — — — > account.ext

— — — — — — > wallet.ext

Where “main_program.ext” is the example file showcasing how to leverage all files under /utils containing the functions for generating deterministic accounts.

Disclaimer

Please note that these are our own internal tools that we are opening up to the wider Algorand developer community and that they have not been audited. Use at your own risk. Any unexpected issues that might arise from the use of these tools is on the onus of you as the user and by the use of these tools you agree that Yieldly is not liable for any damages that may occur. We do not maintain this blog.

Final Word

Our team likes to constantly push the boundaries and help grow the ecosystem through helpful tools such as this where we can. If you have any more requests or wish for us to investigate/scope new tools, join our Twitter, Telegram Group and Announcements, and Discord channel to become part of the conversation.

--

--