Web3j ist ein sehr modularer und typsichere Library für Java und Android. Viele Module und Funktionen für das einfache arbeiten mit Smart-Contracts und Wallets auf der Ethereum-Blockchain (ETH), stehen bereit.
Hier nun ein kleines Beispiel, wie mit nur einer Java-Klasse und ein paar Zeilen Code ein eigenes File-Wallet im Json-Format erstellt werden kann. In einem weiteren Beitrag zeige ich dann, wie dieses File-Wallet in MetaMask importiert werden kann.
Folgende Abhängigkeiten sind in der pom.xml einzutragen, Web3j und die „alte“ (alt aber Apache) Json-Lib von Google, obwohl Web3j auch die Jackson Json Lib als transitive Abhängigkeit mitbringt. Es muss ja nicht immer Jackson sein 😉
1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- Zum bearbeiten von Json --> <dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>1.1.1</version> </dependency> <!-- ETH Blockchain WEB3j --> <dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>4.8.7</version> </dependency> |
Die LocalWallet Klasse, braucht für den Aufruf nur ein Passwort.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
package de.wenzlaff.blockchain; import java.io.File; import java.io.FileReader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.web3j.crypto.WalletUtils; /** * Erzeugt ein Wallet in einem Json File. * * Aufruf: LocalWallet [Passwort] * * z.B. * * LocalWallet geheim * * Erzeugt z.B. solch ein Json File: * * <pre> { "address": "1486df323a85999fb6a540492dc8725c8ecdfb9b", "id": "12a615ec-1926-4a0c-b6c9-355d525c3fd1", "version": 3, "crypto": { "cipher": "aes-128-ctr", "ciphertext": "a367817d4cb23e822d4f46ec726dd7717f20f3e19a1b651382bc7b156a2bf306", "cipherparams": { "iv": "f60a43fa2d8a0fc988e430f4f63d70e8" }, "kdf": "scrypt", "kdfparams": { "dklen": 32, "n": 262144, "p": 1, "r": 8, "salt": "4c9e3b621a9df62fb5e1aaa9323ca6c508908976af0adb4f5680685c13d1bde9" }, "mac": "248f3ccfcca62b810ef63daef1bec2633c96c657712f75f056e0c9c9e379083a" } } * </pre> * * Auf die Adresse des erzeugten Wallets aus dem File z.B. "address": * "8e031f1c47537910fe104936dcd0f77f8a97c6f1", per MetaMask Guthaben überweisen * * @author Thomas Wenzlaff */ public class LocalWallet { private static final Logger LOG = LogManager.getLogger(LocalWallet.class); /** * Startet das generieren eines File Wallets * * @param args Passwort * @throws Exception bei Fehlern */ public static void main(String[] args) throws Exception { if (args.length == 0 || args[0].isEmpty()) { LOG.error("Passwort nicht als Programmparameter gesetzt!"); return; } String password = args[0]; LocalWallet localWallet = new LocalWallet(); String jsonWalletFileName = localWallet.createWallet(password); LOG.info("Erzeugte Wallet Adresse: " + localWallet.readJsonWallet(jsonWalletFileName).get("address")); } /** * Erzeugt das Json Wallet. * * @param password das Passwort * @throws Exception bei Fehlern */ private String createWallet(String password) throws Exception { String generateWalletFileName = WalletUtils.generateNewWalletFile(password, new File(".")); System.out.println("Wallet mit Passwort: " + password + " in Json Datei: " + generateWalletFileName + " erzeugt."); return generateWalletFileName; } /** * Liest eine Json Wallet Datei und gib sie als Json Objekt zurück. * * @param walletDateiName der Dateiname * @return das File Wallet als Json */ private JSONObject readJsonWallet(String walletDateiName) { JSONObject wallet = null; try (FileReader reader = new FileReader(walletDateiName)) { Object obj = new JSONParser().parse(reader); wallet = (JSONObject) obj; } catch (Exception e) { LOG.error("Fehler beim einlesen des Wallets", e); } return wallet; } } |
Die Musik spielt eigentlich nur in der Zeile 71, wo mit createWallet und einem Passwort die Json-Wallet angelegt wird. Hier eine Json Beispiel Wallet, nach dieser Spec. mit Testvektoren.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "address": "1486df323a85999fb6a540492dc8725c8ecdfb9b", "id": "12a615ec-1926-4a0c-b6c9-355d525c3fd1", "version": 3, "crypto": { "cipher": "aes-128-ctr", "ciphertext": "a367817d4cb23e822d4f46ec726dd7717f20f3e19a1b651382bc7b156a2bf306", "cipherparams": { "iv": "f60a43fa2d8a0fc988e430f4f63d70e8" }, "kdf": "scrypt", "kdfparams": { "dklen": 32, "n": 262144, "p": 1, "r": 8, "salt": "4c9e3b621a9df62fb5e1aaa9323ca6c508908976af0adb4f5680685c13d1bde9" }, "mac": "248f3ccfcca62b810ef63daef1bec2633c96c657712f75f056e0c9c9e379083a" } } |
Man kann aber auch, mit der eigenen Web3j-Util Funktion leicht, ohne Json die Adresse ermitteln. Dazu kann man den Credentials Wrapper verwenden, der auch noch einige andere Funktionen mitbringt (get ECKeyPair, Elliptic Curve SECP-256k1 generated key pair.) um z.B. den privaten oder public Key zu ermitteln.
1 2 3 4 |
Credentials credentials = WalletUtils.loadCredentials(password, jsonWalletFileName); LOG.info("Credential: " + credentials.getAddress()); LOG.info("Private Key: " + credentials.getEcKeyPair().getPrivateKey()); LOG.info("Public Key : " + credentials.getEcKeyPair().getPublicKey()); |