/* * Copyright 2014 Andreas Schildbach * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bitcoinj.crypto; import org.bitcoinj.core.ECKey; import org.bitcoinj.crypto.BIP38PrivateKey.BadPassphraseException; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.TestNet3Params; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; public class BIP38PrivateKeyTest { private static final MainNetParams MAINNET = MainNetParams.get(); private static final TestNet3Params TESTNET = TestNet3Params.get(); @Test public void bip38testvector_noCompression_noEcMultiply_test1() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MAINNET, "6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg"); ECKey key = encryptedKey.decrypt("TestingOneTwoThree"); assertEquals("5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_noCompression_noEcMultiply_test2() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MAINNET, "6PRNFFkZc2NZ6dJqFfhRoFNMR9Lnyj7dYGrzdgXXVMXcxoKTePPX1dWByq"); ECKey key = encryptedKey.decrypt("Satoshi"); assertEquals("5HtasZ6ofTHP6HCwTqTkLDuLQisYPah7aUnSKfC7h4hMUVw2gi5", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_noCompression_noEcMultiply_test3() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MAINNET, "6PRW5o9FLp4gJDDVqJQKJFTpMvdsSGJxMYHtHaQBF3ooa8mwD69bapcDQn"); StringBuilder passphrase = new StringBuilder(); passphrase.appendCodePoint(0x03d2); // GREEK UPSILON WITH HOOK passphrase.appendCodePoint(0x0301); // COMBINING ACUTE ACCENT passphrase.appendCodePoint(0x0000); // NULL passphrase.appendCodePoint(0x010400); // DESERET CAPITAL LETTER LONG I passphrase.appendCodePoint(0x01f4a9); // PILE OF POO ECKey key = encryptedKey.decrypt(passphrase.toString()); assertEquals("5Jajm8eQ22H3pGWLEVCXyvND8dQZhiQhoLJNKjYXk9roUFTMSZ4", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_compression_noEcMultiply_test1() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MainNetParams.get(), "6PYNKZ1EAgYgmQfmNVamxyXVWHzK5s6DGhwP4J5o44cvXdoY7sRzhtpUeo"); ECKey key = encryptedKey.decrypt("TestingOneTwoThree"); assertEquals("L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_compression_noEcMultiply_test2() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MainNetParams.get(), "6PYLtMnXvfG3oJde97zRyLYFZCYizPU5T3LwgdYJz1fRhh16bU7u6PPmY7"); ECKey key = encryptedKey.decrypt("Satoshi"); assertEquals("KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_ecMultiply_noCompression_noLotAndSequence_test1() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MainNetParams.get(), "6PfQu77ygVyJLZjfvMLyhLMQbYnu5uguoJJ4kMCLqWwPEdfpwANVS76gTX"); ECKey key = encryptedKey.decrypt("TestingOneTwoThree"); assertEquals("5K4caxezwjGCGfnoPTZ8tMcJBLB7Jvyjv4xxeacadhq8nLisLR2", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_ecMultiply_noCompression_noLotAndSequence_test2() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MainNetParams.get(), "6PfLGnQs6VZnrNpmVKfjotbnQuaJK4KZoPFrAjx1JMJUa1Ft8gnf5WxfKd"); ECKey key = encryptedKey.decrypt("Satoshi"); assertEquals("5KJ51SgxWaAYR13zd9ReMhJpwrcX47xTJh2D3fGPG9CM8vkv5sH", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_ecMultiply_noCompression_lotAndSequence_test1() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MainNetParams.get(), "6PgNBNNzDkKdhkT6uJntUXwwzQV8Rr2tZcbkDcuC9DZRsS6AtHts4Ypo1j"); ECKey key = encryptedKey.decrypt("MOLON LABE"); assertEquals("5JLdxTtcTHcfYcmJsNVy1v2PMDx432JPoYcBTVVRHpPaxUrdtf8", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bip38testvector_ecMultiply_noCompression_lotAndSequence_test2() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MainNetParams.get(), "6PgGWtx25kUg8QWvwuJAgorN6k9FbE25rv5dMRwu5SKMnfpfVe5mar2ngH"); ECKey key = encryptedKey.decrypt("ΜΟΛΩΝ ΛΑΒΕ"); assertEquals("5KMKKuUmAkiNbA3DazMQiLfDq47qs8MAEThm4yL8R2PhV1ov33D", key.getPrivateKeyEncoded(MAINNET) .toString()); } @Test public void bitcoinpaperwallet_testnet() throws Exception { // values taken from bitcoinpaperwallet.com BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(TESTNET, "6PRPhQhmtw6dQu6jD8E1KS4VphwJxBS9Eh9C8FQELcrwN3vPvskv9NKvuL"); ECKey key = encryptedKey.decrypt("password"); assertEquals("93MLfjbY6ugAsLeQfFY6zodDa8izgm1XAwA9cpMbUTwLkDitopg", key.getPrivateKeyEncoded(TESTNET) .toString()); } @Test public void bitaddress_testnet() throws Exception { // values taken from bitaddress.org BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(TESTNET, "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb"); ECKey key = encryptedKey.decrypt("password"); assertEquals("91tCpdaGr4Khv7UAuUxa6aMqeN5GcPVJxzLtNsnZHTCndxkRcz2", key.getPrivateKeyEncoded(TESTNET) .toString()); } @Test(expected = BadPassphraseException.class) public void badPassphrase() throws Exception { BIP38PrivateKey encryptedKey = BIP38PrivateKey.fromBase58(MAINNET, "6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg"); encryptedKey.decrypt("BAD"); } @Test public void testJavaSerialization() throws Exception { BIP38PrivateKey testKey = BIP38PrivateKey.fromBase58(TESTNET, "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb"); ByteArrayOutputStream os = new ByteArrayOutputStream(); new ObjectOutputStream(os).writeObject(testKey); BIP38PrivateKey testKeyCopy = (BIP38PrivateKey) new ObjectInputStream( new ByteArrayInputStream(os.toByteArray())).readObject(); assertEquals(testKey, testKeyCopy); BIP38PrivateKey mainKey = BIP38PrivateKey.fromBase58(MAINNET, "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb"); os = new ByteArrayOutputStream(); new ObjectOutputStream(os).writeObject(mainKey); BIP38PrivateKey mainKeyCopy = (BIP38PrivateKey) new ObjectInputStream( new ByteArrayInputStream(os.toByteArray())).readObject(); assertEquals(mainKey, mainKeyCopy); } @Test public void cloning() throws Exception { BIP38PrivateKey a = BIP38PrivateKey.fromBase58(TESTNET, "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb"); // TODO: Consider overriding clone() in BIP38PrivateKey to narrow the type BIP38PrivateKey b = (BIP38PrivateKey) a.clone(); assertEquals(a, b); assertNotSame(a, b); } @Test public void roundtripBase58() throws Exception { String base58 = "6PfMmVHn153N3x83Yiy4Nf76dHUkXufe2Adr9Fw5bewrunGNeaw2QCpifb"; assertEquals(base58, BIP38PrivateKey.fromBase58(MAINNET, base58).toBase58()); } }