Fixes and improvements, SystemTest still broken
This commit is contained in:
@ -15,5 +15,6 @@ dependencies {
|
||||
compile 'org.ini4j:ini4j:0.5.4'
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.mockito:mockito-core:2.7.21'
|
||||
testCompile 'com.nhaarman:mockito-kotlin:1.4.0'
|
||||
testCompile project(':cryptography-bc')
|
||||
}
|
||||
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif;
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.exception.ApplicationException;
|
||||
import ch.dissem.bitmessage.utils.Base58;
|
||||
import org.ini4j.Ini;
|
||||
import org.ini4j.Profile;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collection;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.valueobject.PrivateKey.PRIVATE_KEY_SIZE;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class WifExporter {
|
||||
private final BitmessageContext ctx;
|
||||
private final Ini ini;
|
||||
|
||||
public WifExporter(BitmessageContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.ini = new Ini();
|
||||
}
|
||||
|
||||
public WifExporter addAll() {
|
||||
for (BitmessageAddress identity : ctx.addresses().getIdentities()) {
|
||||
addIdentity(identity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WifExporter addAll(Collection<BitmessageAddress> identities) {
|
||||
for (BitmessageAddress identity : identities) {
|
||||
addIdentity(identity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WifExporter addIdentity(BitmessageAddress identity) {
|
||||
Profile.Section section = ini.add(identity.getAddress());
|
||||
section.add("label", identity.getAlias());
|
||||
section.add("enabled", true);
|
||||
section.add("decoy", false);
|
||||
if (identity.isChan()) {
|
||||
section.add("chan", identity.isChan());
|
||||
}
|
||||
section.add("noncetrialsperbyte", identity.getPubkey().getNonceTrialsPerByte());
|
||||
section.add("payloadlengthextrabytes", identity.getPubkey().getExtraBytes());
|
||||
section.add("privsigningkey", exportSecret(identity.getPrivateKey().getPrivateSigningKey()));
|
||||
section.add("privencryptionkey", exportSecret(identity.getPrivateKey().getPrivateEncryptionKey()));
|
||||
return this;
|
||||
}
|
||||
|
||||
private String exportSecret(byte[] privateKey) {
|
||||
if (privateKey.length != PRIVATE_KEY_SIZE) {
|
||||
throw new IllegalArgumentException("Private key of length 32 expected, but was " + privateKey.length);
|
||||
}
|
||||
byte[] result = new byte[37];
|
||||
result[0] = (byte) 0x80;
|
||||
System.arraycopy(privateKey, 0, result, 1, PRIVATE_KEY_SIZE);
|
||||
byte[] hash = cryptography().doubleSha256(result, PRIVATE_KEY_SIZE + 1);
|
||||
System.arraycopy(hash, 0, result, PRIVATE_KEY_SIZE + 1, 4);
|
||||
return Base58.encode(result);
|
||||
}
|
||||
|
||||
public void write(File file) throws IOException {
|
||||
file.createNewFile();
|
||||
try (FileOutputStream out = new FileOutputStream(file)) {
|
||||
write(out);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(OutputStream out) throws IOException {
|
||||
ini.store(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringWriter writer = new StringWriter();
|
||||
try {
|
||||
ini.store(writer);
|
||||
} catch (IOException e) {
|
||||
throw new ApplicationException(e);
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
103
wif/src/main/java/ch/dissem/bitmessage/wif/WifExporter.kt
Normal file
103
wif/src/main/java/ch/dissem/bitmessage/wif/WifExporter.kt
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2017 Christian Basler
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey.Companion.PRIVATE_KEY_SIZE
|
||||
import ch.dissem.bitmessage.utils.Base58
|
||||
import ch.dissem.bitmessage.utils.Singleton.cryptography
|
||||
import org.ini4j.Ini
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.StringWriter
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
class WifExporter(private val ctx: BitmessageContext) {
|
||||
private val ini = Ini()
|
||||
|
||||
fun addAll(): WifExporter {
|
||||
ctx.addresses.getIdentities().forEach { addIdentity(it) }
|
||||
return this
|
||||
}
|
||||
|
||||
fun addAll(identities: Collection<BitmessageAddress>): WifExporter {
|
||||
identities.forEach { addIdentity(it) }
|
||||
return this
|
||||
}
|
||||
|
||||
fun addIdentity(identity: BitmessageAddress): WifExporter {
|
||||
val section = ini.add(identity.address)
|
||||
section.add("label", identity.alias)
|
||||
section.add("enabled", true)
|
||||
section.add("decoy", false)
|
||||
if (identity.isChan) {
|
||||
section.add("chan", identity.isChan)
|
||||
}
|
||||
section.add("noncetrialsperbyte", identity.pubkey!!.nonceTrialsPerByte)
|
||||
section.add("payloadlengthextrabytes", identity.pubkey!!.extraBytes)
|
||||
section.add("privsigningkey", exportSecret(identity.privateKey!!.privateSigningKey))
|
||||
section.add("privencryptionkey", exportSecret(identity.privateKey!!.privateEncryptionKey))
|
||||
return this
|
||||
}
|
||||
|
||||
private fun exportSecret(privateKey: ByteArray): String {
|
||||
if (privateKey.size != PRIVATE_KEY_SIZE) {
|
||||
throw IllegalArgumentException("Private key of length 32 expected, but was " + privateKey.size)
|
||||
}
|
||||
val result = ByteArray(37)
|
||||
result[0] = 0x80.toByte()
|
||||
System.arraycopy(privateKey, 0, result, 1, PRIVATE_KEY_SIZE)
|
||||
val hash = cryptography().doubleSha256(result, PRIVATE_KEY_SIZE + 1)
|
||||
System.arraycopy(hash, 0, result, PRIVATE_KEY_SIZE + 1, 4)
|
||||
return Base58.encode(result)
|
||||
}
|
||||
|
||||
fun write(file: File) {
|
||||
file.createNewFile()
|
||||
FileOutputStream(file).use { out -> write(out) }
|
||||
}
|
||||
|
||||
fun write(out: OutputStream) {
|
||||
ini.store(out)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val writer = StringWriter()
|
||||
ini.store(writer)
|
||||
return writer.toString()
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif;
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||
import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.utils.Base58;
|
||||
import org.ini4j.Ini;
|
||||
import org.ini4j.Profile;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class WifImporter {
|
||||
private static final byte WIF_FIRST_BYTE = (byte) 0x80;
|
||||
private static final int WIF_SECRET_LENGTH = 37;
|
||||
|
||||
private final BitmessageContext ctx;
|
||||
private final List<BitmessageAddress> identities = new LinkedList<>();
|
||||
|
||||
public WifImporter(BitmessageContext ctx, File file) throws IOException {
|
||||
this(ctx, new FileInputStream(file));
|
||||
}
|
||||
|
||||
public WifImporter(BitmessageContext ctx, String data) throws IOException {
|
||||
this(ctx, new ByteArrayInputStream(data.getBytes("utf-8")));
|
||||
}
|
||||
|
||||
public WifImporter(BitmessageContext ctx, InputStream in, Pubkey.Feature... features) throws IOException {
|
||||
this.ctx = ctx;
|
||||
|
||||
Ini ini = new Ini();
|
||||
ini.load(in);
|
||||
|
||||
for (Entry<String, Profile.Section> entry : ini.entrySet()) {
|
||||
if (!entry.getKey().startsWith("BM-"))
|
||||
continue;
|
||||
|
||||
Profile.Section section = entry.getValue();
|
||||
BitmessageAddress address = Factory.createIdentityFromPrivateKey(
|
||||
entry.getKey(),
|
||||
getSecret(section.get("privsigningkey")),
|
||||
getSecret(section.get("privencryptionkey")),
|
||||
Long.parseLong(section.get("noncetrialsperbyte")),
|
||||
Long.parseLong(section.get("payloadlengthextrabytes")),
|
||||
Pubkey.Feature.bitfield(features)
|
||||
);
|
||||
if (section.containsKey("chan")) {
|
||||
address.setChan(Boolean.parseBoolean(section.get("chan")));
|
||||
}
|
||||
address.setAlias(section.get("label"));
|
||||
identities.add(address);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getSecret(String walletImportFormat) throws IOException {
|
||||
byte[] bytes = Base58.decode(walletImportFormat);
|
||||
if (bytes[0] != WIF_FIRST_BYTE)
|
||||
throw new IOException("Unknown format: 0x80 expected as first byte, but secret " + walletImportFormat +
|
||||
" was " + bytes[0]);
|
||||
if (bytes.length != WIF_SECRET_LENGTH)
|
||||
throw new IOException("Unknown format: " + WIF_SECRET_LENGTH +
|
||||
" bytes expected, but secret " + walletImportFormat + " was " + bytes.length + " long");
|
||||
|
||||
byte[] hash = cryptography().doubleSha256(bytes, 33);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (hash[i] != bytes[33 + i]) throw new IOException("Hash check failed for secret " + walletImportFormat);
|
||||
}
|
||||
return Arrays.copyOfRange(bytes, 1, 33);
|
||||
}
|
||||
|
||||
public List<BitmessageAddress> getIdentities() {
|
||||
return identities;
|
||||
}
|
||||
|
||||
public WifImporter importAll() {
|
||||
for (BitmessageAddress identity : identities) {
|
||||
ctx.addresses().save(identity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WifImporter importAll(Collection<BitmessageAddress> identities) {
|
||||
for (BitmessageAddress identity : identities) {
|
||||
ctx.addresses().save(identity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public WifImporter importIdentity(BitmessageAddress identity) {
|
||||
ctx.addresses().save(identity);
|
||||
return this;
|
||||
}
|
||||
}
|
126
wif/src/main/java/ch/dissem/bitmessage/wif/WifImporter.kt
Normal file
126
wif/src/main/java/ch/dissem/bitmessage/wif/WifImporter.kt
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2017 Christian Basler
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey
|
||||
import ch.dissem.bitmessage.exception.ApplicationException
|
||||
import ch.dissem.bitmessage.factory.Factory
|
||||
import ch.dissem.bitmessage.utils.Base58
|
||||
import ch.dissem.bitmessage.utils.Singleton.cryptography
|
||||
import org.ini4j.Ini
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
class WifImporter constructor(
|
||||
private val ctx: BitmessageContext,
|
||||
`in`: InputStream,
|
||||
vararg features: Pubkey.Feature
|
||||
) {
|
||||
private val identities = LinkedList<BitmessageAddress>()
|
||||
|
||||
constructor(ctx: BitmessageContext, file: File) : this(ctx, FileInputStream(file))
|
||||
|
||||
constructor(ctx: BitmessageContext, data: String) : this(ctx, ByteArrayInputStream(data.toByteArray(charset("utf-8"))))
|
||||
|
||||
init {
|
||||
val ini = Ini()
|
||||
ini.load(`in`)
|
||||
|
||||
for ((key, section) in ini) {
|
||||
if (!key.startsWith("BM-"))
|
||||
continue
|
||||
|
||||
val address = Factory.createIdentityFromPrivateKey(
|
||||
key,
|
||||
getSecret(section["privsigningkey"] ?: throw ApplicationException("privsigningkey missing for $key")),
|
||||
getSecret(section["privencryptionkey"] ?: throw ApplicationException("privencryptionkey missing for $key")),
|
||||
section["noncetrialsperbyte"]?.toLongOrNull() ?: throw ApplicationException("noncetrialsperbyte missing for $key"),
|
||||
section["payloadlengthextrabytes"]?.toLongOrNull() ?: throw ApplicationException("payloadlengthextrabytes missing for $key"),
|
||||
Pubkey.Feature.bitfield(*features)
|
||||
)
|
||||
if (section.containsKey("chan")) {
|
||||
address.isChan = java.lang.Boolean.parseBoolean(section["chan"])
|
||||
}
|
||||
address.alias = section["label"]
|
||||
identities.add(address)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSecret(walletImportFormat: String): ByteArray {
|
||||
val bytes = Base58.decode(walletImportFormat)
|
||||
if (bytes[0] != WIF_FIRST_BYTE)
|
||||
throw ApplicationException("Unknown format: 0x80 expected as first byte, but secret " + walletImportFormat +
|
||||
" was " + bytes[0])
|
||||
if (bytes.size != WIF_SECRET_LENGTH)
|
||||
throw ApplicationException("Unknown format: " + WIF_SECRET_LENGTH +
|
||||
" bytes expected, but secret " + walletImportFormat + " was " + bytes.size + " long")
|
||||
|
||||
val hash = cryptography().doubleSha256(bytes, 33)
|
||||
(0..3)
|
||||
.filter { hash[it] != bytes[33 + it] }
|
||||
.forEach { throw ApplicationException("Hash check failed for secret " + walletImportFormat) }
|
||||
return Arrays.copyOfRange(bytes, 1, 33)
|
||||
}
|
||||
|
||||
fun getIdentities(): List<BitmessageAddress> {
|
||||
return identities
|
||||
}
|
||||
|
||||
fun importAll(): WifImporter {
|
||||
identities.forEach { ctx.addresses.save(it) }
|
||||
return this
|
||||
}
|
||||
|
||||
fun importAll(identities: Collection<BitmessageAddress>): WifImporter {
|
||||
identities.forEach { ctx.addresses.save(it) }
|
||||
return this
|
||||
}
|
||||
|
||||
fun importIdentity(identity: BitmessageAddress): WifImporter {
|
||||
ctx.addresses.save(identity)
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val WIF_FIRST_BYTE = 0x80.toByte()
|
||||
private const val WIF_SECRET_LENGTH = 37
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif;
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.ports.*;
|
||||
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class WifExporterTest {
|
||||
private AddressRepository repo = mock(AddressRepository.class);
|
||||
private BitmessageContext ctx;
|
||||
private WifImporter importer;
|
||||
private WifExporter exporter;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
ctx = new BitmessageContext.Builder()
|
||||
.cryptography(BouncyCryptography.INSTANCE)
|
||||
.networkHandler(mock(NetworkHandler.class))
|
||||
.inventory(mock(Inventory.class))
|
||||
.messageRepo(mock(MessageRepository.class))
|
||||
.powRepo(mock(ProofOfWorkRepository.class))
|
||||
.nodeRegistry(mock(NodeRegistry.class))
|
||||
.addressRepo(repo)
|
||||
.build();
|
||||
importer = new WifImporter(ctx, getClass().getClassLoader().getResourceAsStream("nuked.dat"));
|
||||
assertEquals(81, importer.getIdentities().size());
|
||||
exporter = new WifExporter(ctx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAll() throws Exception {
|
||||
when(repo.getIdentities()).thenReturn(importer.getIdentities());
|
||||
exporter.addAll();
|
||||
String result = exporter.toString();
|
||||
int count = 0;
|
||||
for (int i = 0; i < result.length(); i++) {
|
||||
if (result.charAt(i) == '[') count++;
|
||||
}
|
||||
assertEquals(importer.getIdentities().size(), count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAllFromCollection() throws Exception {
|
||||
exporter.addAll(importer.getIdentities());
|
||||
String result = exporter.toString();
|
||||
int count = 0;
|
||||
for (int i = 0; i < result.length(); i++) {
|
||||
if (result.charAt(i) == '[') count++;
|
||||
}
|
||||
assertEquals(importer.getIdentities().size(), count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddIdentity() throws Exception {
|
||||
String expected = "[BM-2DAjcCFrqFrp88FUxExhJ9kPqHdunQmiyn]" + System.lineSeparator() +
|
||||
"label = Nuked Address" + System.lineSeparator() +
|
||||
"enabled = true" + System.lineSeparator() +
|
||||
"decoy = false" + System.lineSeparator() +
|
||||
"noncetrialsperbyte = 320" + System.lineSeparator() +
|
||||
"payloadlengthextrabytes = 14000" + System.lineSeparator() +
|
||||
"privsigningkey = 5KU2gbe9u4rKJ8PHYb1rvwMnZnAJj4gtV5GLwoYckeYzygWUzB9" + System.lineSeparator() +
|
||||
"privencryptionkey = 5KHd4c6cavd8xv4kzo3PwnVaYuBgEfg7voPQ5V97aZKgpYBXGck" + System.lineSeparator() +
|
||||
System.lineSeparator();
|
||||
importer = new WifImporter(ctx, expected);
|
||||
exporter.addIdentity(importer.getIdentities().get(0));
|
||||
assertEquals(expected, exporter.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureChanIsAdded() throws Exception {
|
||||
String expected = "[BM-2cW67GEKkHGonXKZLCzouLLxnLym3azS8r]" + System.lineSeparator() +
|
||||
"label = general" + System.lineSeparator() +
|
||||
"enabled = true" + System.lineSeparator() +
|
||||
"decoy = false" + System.lineSeparator() +
|
||||
"chan = true" + System.lineSeparator() +
|
||||
"noncetrialsperbyte = 1000" + System.lineSeparator() +
|
||||
"payloadlengthextrabytes = 1000" + System.lineSeparator() +
|
||||
"privsigningkey = 5Jnbdwc4u4DG9ipJxYLznXSvemkRFueQJNHujAQamtDDoX3N1eQ" + System.lineSeparator() +
|
||||
"privencryptionkey = 5JrDcFtQDv5ydcHRW6dfGUEvThoxCCLNEUaxQfy8LXXgTJzVAcq" + System.lineSeparator() +
|
||||
System.lineSeparator();
|
||||
BitmessageAddress chan = ctx.joinChan("general", "BM-2cW67GEKkHGonXKZLCzouLLxnLym3azS8r");
|
||||
exporter.addIdentity(chan);
|
||||
assertEquals(expected, exporter.toString());
|
||||
}
|
||||
}
|
122
wif/src/test/java/ch/dissem/bitmessage/wif/WifExporterTest.kt
Normal file
122
wif/src/test/java/ch/dissem/bitmessage/wif/WifExporterTest.kt
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2017 Christian Basler
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography
|
||||
import ch.dissem.bitmessage.ports.AddressRepository
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.nhaarman.mockito_kotlin.whenever
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class WifExporterTest {
|
||||
private val repo = mock<AddressRepository>()
|
||||
private lateinit var ctx: BitmessageContext
|
||||
private lateinit var importer: WifImporter
|
||||
private lateinit var exporter: WifExporter
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
ctx = BitmessageContext.Builder()
|
||||
.cryptography(BouncyCryptography())
|
||||
.networkHandler(mock())
|
||||
.inventory(mock())
|
||||
.messageRepo(mock())
|
||||
.powRepo(mock())
|
||||
.nodeRegistry(mock())
|
||||
.addressRepo(repo)
|
||||
.listener { }
|
||||
.build()
|
||||
importer = WifImporter(ctx, javaClass.classLoader.getResourceAsStream("nuked.dat"))
|
||||
assertEquals(81, importer.getIdentities().size)
|
||||
exporter = WifExporter(ctx)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure all identities in context are added`() {
|
||||
whenever(repo.getIdentities()).thenReturn(importer.getIdentities())
|
||||
exporter.addAll()
|
||||
val result = exporter.toString()
|
||||
var count = 0
|
||||
for (i in 0..result.length - 1) {
|
||||
if (result[i] == '[') count++
|
||||
}
|
||||
assertEquals(importer.getIdentities().size, count)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure all from a collection are added`() {
|
||||
exporter.addAll(importer.getIdentities())
|
||||
val result = exporter.toString()
|
||||
var count = 0
|
||||
for (i in 0..result.length - 1) {
|
||||
if (result[i] == '[') count++
|
||||
}
|
||||
assertEquals(importer.getIdentities().size, count)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure identity is added`() {
|
||||
val expected = "[BM-2DAjcCFrqFrp88FUxExhJ9kPqHdunQmiyn]" + System.lineSeparator() +
|
||||
"label = Nuked Address" + System.lineSeparator() +
|
||||
"enabled = true" + System.lineSeparator() +
|
||||
"decoy = false" + System.lineSeparator() +
|
||||
"noncetrialsperbyte = 320" + System.lineSeparator() +
|
||||
"payloadlengthextrabytes = 14000" + System.lineSeparator() +
|
||||
"privsigningkey = 5KU2gbe9u4rKJ8PHYb1rvwMnZnAJj4gtV5GLwoYckeYzygWUzB9" + System.lineSeparator() +
|
||||
"privencryptionkey = 5KHd4c6cavd8xv4kzo3PwnVaYuBgEfg7voPQ5V97aZKgpYBXGck" + System.lineSeparator() +
|
||||
System.lineSeparator()
|
||||
importer = WifImporter(ctx, expected)
|
||||
exporter.addIdentity(importer.getIdentities()[0])
|
||||
assertEquals(expected, exporter.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure chan is added`() {
|
||||
val expected = "[BM-2cW67GEKkHGonXKZLCzouLLxnLym3azS8r]" + System.lineSeparator() +
|
||||
"label = general" + System.lineSeparator() +
|
||||
"enabled = true" + System.lineSeparator() +
|
||||
"decoy = false" + System.lineSeparator() +
|
||||
"chan = true" + System.lineSeparator() +
|
||||
"noncetrialsperbyte = 1000" + System.lineSeparator() +
|
||||
"payloadlengthextrabytes = 1000" + System.lineSeparator() +
|
||||
"privsigningkey = 5Jnbdwc4u4DG9ipJxYLznXSvemkRFueQJNHujAQamtDDoX3N1eQ" + System.lineSeparator() +
|
||||
"privencryptionkey = 5JrDcFtQDv5ydcHRW6dfGUEvThoxCCLNEUaxQfy8LXXgTJzVAcq" + System.lineSeparator() +
|
||||
System.lineSeparator()
|
||||
val chan = ctx.joinChan("general", "BM-2cW67GEKkHGonXKZLCzouLLxnLym3azS8r")
|
||||
exporter.addIdentity(chan)
|
||||
assertEquals(expected, exporter.toString())
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif;
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.ports.*;
|
||||
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class WifImporterTest {
|
||||
private AddressRepository repo = mock(AddressRepository.class);
|
||||
private BitmessageContext ctx;
|
||||
private WifImporter importer;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
ctx = new BitmessageContext.Builder()
|
||||
.cryptography(BouncyCryptography.INSTANCE)
|
||||
.networkHandler(mock(NetworkHandler.class))
|
||||
.inventory(mock(Inventory.class))
|
||||
.messageRepo(mock(MessageRepository.class))
|
||||
.powRepo(mock(ProofOfWorkRepository.class))
|
||||
.nodeRegistry(mock(NodeRegistry.class))
|
||||
.addressRepo(repo)
|
||||
.build();
|
||||
importer = new WifImporter(ctx, getClass().getClassLoader().getResourceAsStream("nuked.dat"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testImportSingleIdentity() throws Exception {
|
||||
importer = new WifImporter(ctx, "[BM-2cWJ4UFRTCehWuWNsW8fJkAYMxU4S8jxci]\n" +
|
||||
"label = Nuked Address\n" +
|
||||
"enabled = true\n" +
|
||||
"decoy = false\n" +
|
||||
"noncetrialsperbyte = 320\n" +
|
||||
"payloadlengthextrabytes = 14000\n" +
|
||||
"privsigningkey = 5JU5t2JA58sP5aJwKAcrYg5EpBA9bJPrBSaFfaZ7ogmwTMDCfHL\n" +
|
||||
"privencryptionkey = 5Kkx5MwjQcM4kyduKvCEPM6nVNynMdRcg88VQ5iVDWUekMz1igH");
|
||||
assertEquals(1, importer.getIdentities().size());
|
||||
BitmessageAddress identity = importer.getIdentities().get(0);
|
||||
assertEquals("BM-2cWJ4UFRTCehWuWNsW8fJkAYMxU4S8jxci", identity.getAddress());
|
||||
assertEquals("Nuked Address", identity.getAlias());
|
||||
assertEquals(320, identity.getPubkey().getNonceTrialsPerByte());
|
||||
assertEquals(14000, identity.getPubkey().getExtraBytes());
|
||||
assertNotNull("Private key", identity.getPrivateKey());
|
||||
assertEquals(32, identity.getPrivateKey().getPrivateEncryptionKey().length);
|
||||
assertEquals(32, identity.getPrivateKey().getPrivateSigningKey().length);
|
||||
assertFalse(identity.isChan());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIdentities() throws Exception {
|
||||
List<BitmessageAddress> identities = importer.getIdentities();
|
||||
assertEquals(81, identities.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportAll() throws Exception {
|
||||
importer.importAll();
|
||||
verify(repo, times(81)).save(any(BitmessageAddress.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportAllFromCollection() throws Exception {
|
||||
List<BitmessageAddress> identities = importer.getIdentities();
|
||||
importer.importAll(identities);
|
||||
for (BitmessageAddress identity : identities) {
|
||||
verify(repo, times(1)).save(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImportIdentity() throws Exception {
|
||||
List<BitmessageAddress> identities = importer.getIdentities();
|
||||
importer.importIdentity(identities.get(0));
|
||||
verify(repo, times(1)).save(identities.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureChanIsImported() throws Exception {
|
||||
importer = new WifImporter(ctx, "[BM-2cW67GEKkHGonXKZLCzouLLxnLym3azS8r]\n" +
|
||||
"label = [chan] general\n" +
|
||||
"enabled = true\n" +
|
||||
"decoy = false\n" +
|
||||
"chan = true\n" +
|
||||
"noncetrialsperbyte = 1000\n" +
|
||||
"payloadlengthextrabytes = 1000\n" +
|
||||
"privsigningkey = 5Jnbdwc4u4DG9ipJxYLznXSvemkRFueQJNHujAQamtDDoX3N1eQ\n" +
|
||||
"privencryptionkey = 5JrDcFtQDv5ydcHRW6dfGUEvThoxCCLNEUaxQfy8LXXgTJzVAcq\n");
|
||||
assertEquals(1, importer.getIdentities().size());
|
||||
BitmessageAddress chan = importer.getIdentities().get(0);
|
||||
assertTrue(chan.isChan());
|
||||
}
|
||||
}
|
132
wif/src/test/java/ch/dissem/bitmessage/wif/WifImporterTest.kt
Normal file
132
wif/src/test/java/ch/dissem/bitmessage/wif/WifImporterTest.kt
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2017 Christian Basler
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* 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 ch.dissem.bitmessage.wif
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography
|
||||
import ch.dissem.bitmessage.ports.AddressRepository
|
||||
import com.nhaarman.mockito_kotlin.any
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.nhaarman.mockito_kotlin.times
|
||||
import com.nhaarman.mockito_kotlin.verify
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class WifImporterTest {
|
||||
private val repo = mock<AddressRepository>()
|
||||
private lateinit var ctx: BitmessageContext
|
||||
private lateinit var importer: WifImporter
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
ctx = BitmessageContext.Builder()
|
||||
.cryptography(BouncyCryptography())
|
||||
.networkHandler(mock())
|
||||
.inventory(mock())
|
||||
.messageRepo(mock())
|
||||
.powRepo(mock())
|
||||
.nodeRegistry(mock())
|
||||
.addressRepo(repo)
|
||||
.listener { }
|
||||
.build()
|
||||
importer = WifImporter(ctx, javaClass.classLoader.getResourceAsStream("nuked.dat"))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `ensure single identity is imported`() {
|
||||
importer = WifImporter(ctx, "[BM-2cWJ4UFRTCehWuWNsW8fJkAYMxU4S8jxci]\n" +
|
||||
"label = Nuked Address\n" +
|
||||
"enabled = true\n" +
|
||||
"decoy = false\n" +
|
||||
"noncetrialsperbyte = 320\n" +
|
||||
"payloadlengthextrabytes = 14000\n" +
|
||||
"privsigningkey = 5JU5t2JA58sP5aJwKAcrYg5EpBA9bJPrBSaFfaZ7ogmwTMDCfHL\n" +
|
||||
"privencryptionkey = 5Kkx5MwjQcM4kyduKvCEPM6nVNynMdRcg88VQ5iVDWUekMz1igH")
|
||||
assertEquals(1, importer.getIdentities().size)
|
||||
val identity = importer.getIdentities()[0]
|
||||
assertEquals("BM-2cWJ4UFRTCehWuWNsW8fJkAYMxU4S8jxci", identity.address)
|
||||
assertEquals("Nuked Address", identity.alias)
|
||||
assertEquals(320L, identity.pubkey?.nonceTrialsPerByte)
|
||||
assertEquals(14000L, identity.pubkey?.extraBytes)
|
||||
assertNotNull("Private key", identity.privateKey)
|
||||
assertEquals(32, identity.privateKey?.privateEncryptionKey?.size)
|
||||
assertEquals(32, identity.privateKey?.privateSigningKey?.size)
|
||||
assertFalse(identity.isChan)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure all identities are retrieved`() {
|
||||
val identities = importer.getIdentities()
|
||||
assertEquals(81, identities.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure all identities are imported`() {
|
||||
importer.importAll()
|
||||
verify(repo, times(81)).save(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure all identities in collection are imported`() {
|
||||
val identities = importer.getIdentities()
|
||||
importer.importAll(identities)
|
||||
for (identity in identities) {
|
||||
verify(repo, times(1)).save(identity)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure single identity from list is imported`() {
|
||||
val identities = importer.getIdentities()
|
||||
importer.importIdentity(identities[0])
|
||||
verify(repo, times(1)).save(identities[0])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure chan is imported`() {
|
||||
importer = WifImporter(ctx, "[BM-2cW67GEKkHGonXKZLCzouLLxnLym3azS8r]\n" +
|
||||
"label = [chan] general\n" +
|
||||
"enabled = true\n" +
|
||||
"decoy = false\n" +
|
||||
"chan = true\n" +
|
||||
"noncetrialsperbyte = 1000\n" +
|
||||
"payloadlengthextrabytes = 1000\n" +
|
||||
"privsigningkey = 5Jnbdwc4u4DG9ipJxYLznXSvemkRFueQJNHujAQamtDDoX3N1eQ\n" +
|
||||
"privencryptionkey = 5JrDcFtQDv5ydcHRW6dfGUEvThoxCCLNEUaxQfy8LXXgTJzVAcq\n")
|
||||
assertEquals(1, importer.getIdentities().size)
|
||||
val chan = importer.getIdentities()[0]
|
||||
assertTrue(chan.isChan)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user