8 changed files with 432 additions and 34 deletions
|
@ -1,10 +1,18 @@
|
|||
package info.frostfs.sdk;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class ArrayHelper {
|
||||
private static final String ERROR_MESSAGE = "One of the input parameters is null";
|
||||
|
||||
private ArrayHelper() {
|
||||
}
|
||||
|
||||
public static byte[] concat(byte[] startArray, byte[] endArray) {
|
||||
if (isNull(startArray) || isNull(endArray)) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
byte[] result = new byte[startArray.length + endArray.length];
|
||||
|
||||
System.arraycopy(startArray, 0, result, 0, startArray.length);
|
||||
|
|
|
@ -16,6 +16,8 @@ public class Base58 {
|
|||
private static final char ENCODED_ZERO = ALPHABET[0];
|
||||
private static final char BASE58_ASCII_MAX_VALUE = 128;
|
||||
private static final int[] INDEXES = new int[BASE58_ASCII_MAX_VALUE];
|
||||
private static final String ERROR_VALUE_MISSING_MESSAGE = "Input value is missing";
|
||||
private static final String ERROR_INVALID_CHARACTER_TEMPLATE = "Invalid character in Base58: 0x%04x";
|
||||
|
||||
static {
|
||||
Arrays.fill(INDEXES, -1);
|
||||
|
@ -29,7 +31,7 @@ public class Base58 {
|
|||
|
||||
public static byte[] base58CheckDecode(String input) {
|
||||
if (StringUtils.isEmpty(input)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
throw new IllegalArgumentException(ERROR_VALUE_MISSING_MESSAGE);
|
||||
}
|
||||
|
||||
byte[] buffer = decode(input);
|
||||
|
@ -50,7 +52,7 @@ public class Base58 {
|
|||
|
||||
public static String base58CheckEncode(byte[] data) {
|
||||
if (isNull(data)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
throw new IllegalArgumentException(ERROR_VALUE_MISSING_MESSAGE);
|
||||
}
|
||||
|
||||
byte[] checksum = getSha256(getSha256(data));
|
||||
|
@ -99,7 +101,7 @@ public class Base58 {
|
|||
char c = input.charAt(i);
|
||||
int digit = c < BASE58_ASCII_MAX_VALUE ? INDEXES[c] : -1;
|
||||
if (digit < 0) {
|
||||
throw new IllegalArgumentException(String.format("Invalid character in Base58: 0x%04x", (int) c));
|
||||
throw new IllegalArgumentException(String.format(ERROR_INVALID_CHARACTER_TEMPLATE, (int) c));
|
||||
}
|
||||
input58[i] = (byte) digit;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.security.NoSuchAlgorithmException;
|
|||
import static java.util.Objects.isNull;
|
||||
|
||||
public class Helper {
|
||||
private static final String ERROR_MESSAGE = "Input value is missing";
|
||||
private static final String SHA256 = "SHA-256";
|
||||
private static final int RIPEMD_160_HASH_BYTE_LENGTH = 20;
|
||||
|
||||
private Helper() {
|
||||
|
@ -18,7 +20,7 @@ public class Helper {
|
|||
|
||||
public static byte[] getRipemd160(byte[] value) {
|
||||
if (isNull(value)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
var hash = new byte[RIPEMD_160_HASH_BYTE_LENGTH];
|
||||
|
@ -30,7 +32,7 @@ public class Helper {
|
|||
|
||||
public static MessageDigest getSha256Instance() {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256");
|
||||
return MessageDigest.getInstance(SHA256);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -38,7 +40,7 @@ public class Helper {
|
|||
|
||||
public static byte[] getSha256(byte[] value) {
|
||||
if (isNull(value)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
return getSha256Instance().digest(value);
|
||||
|
@ -46,15 +48,15 @@ public class Helper {
|
|||
|
||||
public static ByteString getSha256(Message value) {
|
||||
if (isNull(value)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
return ByteString.copyFrom(getSha256(value.toByteArray()));
|
||||
}
|
||||
|
||||
public static String getHexString(byte[] value) {
|
||||
if (isNull(value)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
if (isNull(value) || value.length == 0) {
|
||||
throw new IllegalArgumentException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
return String.format("%0" + (value.length << 1) + "x", new BigInteger(1, value));
|
||||
|
|
|
@ -31,6 +31,8 @@ import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray;
|
|||
|
||||
public class KeyExtension {
|
||||
public static final byte NEO_ADDRESS_VERSION = 0x35;
|
||||
private static final String CURVE_NAME = "secp256r1";
|
||||
private static final String SECURITY_ALGORITHM = "EC";
|
||||
private static final int PS_IN_HASH160 = 0x0C;
|
||||
private static final int DECODE_ADDRESS_LENGTH = 21;
|
||||
private static final int COMPRESSED_PUBLIC_KEY_LENGTH = 33;
|
||||
|
@ -38,6 +40,13 @@ public class KeyExtension {
|
|||
private static final int CHECK_SIG_DESCRIPTOR = ByteBuffer
|
||||
.wrap(getSha256("System.Crypto.CheckSig".getBytes(StandardCharsets.US_ASCII)))
|
||||
.order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
private static final String ERROR_VALUE_MISSING_MESSAGE = "Input value is missing";
|
||||
private static final String ERROR_ENCODED_COMPRESSED_PUBLIC_KEY_TEMPLATE =
|
||||
"PublicKey isn't encoded compressed public key. Expected length=%s, actual=%s";
|
||||
private static final String ERROR_UNCOMPRESSED_PUBLIC_KEY_TEMPLATE =
|
||||
"Compress argument isn't uncompressed public key. Expected length=%s, actual=%s";
|
||||
private static final String ERROR_COMPRESSED_PUBLIC_KEY_TEMPLATE =
|
||||
"Decompress argument isn't compressed public key. Expected length=%s, actual=%s";
|
||||
|
||||
private KeyExtension() {
|
||||
}
|
||||
|
@ -45,10 +54,9 @@ public class KeyExtension {
|
|||
public static byte[] compress(byte[] publicKey) {
|
||||
checkInputValue(publicKey);
|
||||
if (publicKey.length != UNCOMPRESSED_PUBLIC_KEY_LENGTH) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Compress argument isn't uncompressed public key. Expected length=%s, actual=%s",
|
||||
UNCOMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length)
|
||||
);
|
||||
throw new IllegalArgumentException(String.format(
|
||||
ERROR_UNCOMPRESSED_PUBLIC_KEY_TEMPLATE, UNCOMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length
|
||||
));
|
||||
}
|
||||
|
||||
var secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1);
|
||||
|
@ -58,7 +66,7 @@ public class KeyExtension {
|
|||
|
||||
public static byte[] getPrivateKeyFromWIF(String wif) {
|
||||
if (StringUtils.isEmpty(wif)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
throw new IllegalArgumentException(ERROR_VALUE_MISSING_MESSAGE);
|
||||
}
|
||||
|
||||
var data = Base58.base58CheckDecode(wif);
|
||||
|
@ -87,11 +95,11 @@ public class KeyExtension {
|
|||
ECPrivateKeyParameters ecParams = new ECPrivateKeyParameters(fromUnsignedByteArray(privateKey), domain);
|
||||
|
||||
ECParameterSpec ecParameterSpec = new ECNamedCurveSpec(
|
||||
"secp256r1", params.getCurve(), params.getG(), params.getN(), params.getH()
|
||||
CURVE_NAME, params.getCurve(), params.getG(), params.getN(), params.getH()
|
||||
);
|
||||
ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(ecParams.getD(), ecParameterSpec);
|
||||
try {
|
||||
KeyFactory kf = KeyFactory.getInstance("EC");
|
||||
KeyFactory kf = KeyFactory.getInstance(SECURITY_ALGORITHM);
|
||||
return kf.generatePrivate(privateKeySpec);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -103,8 +111,7 @@ public class KeyExtension {
|
|||
|
||||
if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Decompress argument isn't compressed public key. Expected length=%s, actual=%s",
|
||||
COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length)
|
||||
String.format(ERROR_COMPRESSED_PUBLIC_KEY_TEMPLATE, COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -118,13 +125,13 @@ public class KeyExtension {
|
|||
publicParams.getQ().getRawXCoord().toBigInteger(), publicParams.getQ().getRawYCoord().toBigInteger()
|
||||
);
|
||||
ECParameterSpec ecParameterSpec = new ECNamedCurveSpec(
|
||||
"secp256r1", secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(),
|
||||
secp256R1.getH(), secp256R1.getSeed()
|
||||
CURVE_NAME, secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH(),
|
||||
secp256R1.getSeed()
|
||||
);
|
||||
ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(point, ecParameterSpec);
|
||||
|
||||
try {
|
||||
KeyFactory kf = KeyFactory.getInstance("EC");
|
||||
KeyFactory kf = KeyFactory.getInstance(SECURITY_ALGORITHM);
|
||||
return kf.generatePublic(publicKeySpec);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -141,19 +148,18 @@ public class KeyExtension {
|
|||
public static String publicKeyToAddress(byte[] publicKey) {
|
||||
checkInputValue(publicKey);
|
||||
if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("PublicKey isn't encoded compressed public key. Expected length=%s, actual=%s",
|
||||
COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length)
|
||||
);
|
||||
throw new IllegalArgumentException(String.format(
|
||||
ERROR_ENCODED_COMPRESSED_PUBLIC_KEY_TEMPLATE, COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length
|
||||
));
|
||||
}
|
||||
|
||||
return toAddress(getScriptHash(publicKey), NEO_ADDRESS_VERSION);
|
||||
return toAddress(getScriptHash(publicKey));
|
||||
}
|
||||
|
||||
private static String toAddress(byte[] scriptHash, byte version) {
|
||||
private static String toAddress(byte[] scriptHash) {
|
||||
checkInputValue(scriptHash);
|
||||
byte[] data = new byte[DECODE_ADDRESS_LENGTH];
|
||||
data[0] = version;
|
||||
data[0] = NEO_ADDRESS_VERSION;
|
||||
System.arraycopy(scriptHash, 0, data, 1, scriptHash.length);
|
||||
return Base58.base58CheckEncode(data);
|
||||
}
|
||||
|
@ -171,10 +177,9 @@ public class KeyExtension {
|
|||
private static byte[] createSignatureRedeemScript(byte[] publicKey) {
|
||||
checkInputValue(publicKey);
|
||||
if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("PublicKey isn't encoded compressed public key. Expected length=%s, actual=%s",
|
||||
COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length)
|
||||
);
|
||||
throw new IllegalArgumentException(String.format(
|
||||
ERROR_ENCODED_COMPRESSED_PUBLIC_KEY_TEMPLATE, COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length
|
||||
));
|
||||
}
|
||||
|
||||
var script = new byte[]{PS_IN_HASH160, COMPRESSED_PUBLIC_KEY_LENGTH}; //PUSHDATA1 33
|
||||
|
@ -186,8 +191,8 @@ public class KeyExtension {
|
|||
}
|
||||
|
||||
private static void checkInputValue(byte[] data) {
|
||||
if (isNull(data)) {
|
||||
throw new IllegalArgumentException("Input value is missing");
|
||||
if (isNull(data) || data.length == 0) {
|
||||
throw new IllegalArgumentException(ERROR_VALUE_MISSING_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package info.frostfs.sdk;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class ArrayHelperTest {
|
||||
|
||||
@Test
|
||||
void concatTest_success() {
|
||||
//Given
|
||||
var startBytes = new byte[]{1, 2, 3, 4, 5};
|
||||
var endBytes = new byte[]{6, 7, 8, 9};
|
||||
|
||||
//When
|
||||
var result = ArrayHelper.concat(startBytes, endBytes);
|
||||
|
||||
//Then
|
||||
assertThat(startBytes).hasSize(5);
|
||||
assertThat(endBytes).hasSize(4);
|
||||
assertThat(result).hasSize(9).startsWith(startBytes).endsWith(endBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
void concatTest_endArrayIsEmpty() {
|
||||
//Given
|
||||
var startBytes = new byte[]{1, 2, 3, 4, 5};
|
||||
var endBytes = new byte[]{};
|
||||
|
||||
//When
|
||||
var result = ArrayHelper.concat(startBytes, endBytes);
|
||||
|
||||
//Then
|
||||
assertThat(startBytes).hasSize(5);
|
||||
assertThat(endBytes).hasSize(0);
|
||||
assertThat(result).hasSize(5).startsWith(startBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
void concatTest_startArrayIsEmpty() {
|
||||
//Given
|
||||
var startBytes = new byte[]{};
|
||||
var endBytes = new byte[]{6, 7, 8, 9};
|
||||
|
||||
//When
|
||||
var result = ArrayHelper.concat(startBytes, endBytes);
|
||||
|
||||
//Then
|
||||
assertThat(startBytes).hasSize(0);
|
||||
assertThat(endBytes).hasSize(4);
|
||||
assertThat(result).hasSize(4).startsWith(endBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
void concatTest_givenParamsIsNull() {
|
||||
//Given
|
||||
var startBytes = new byte[]{1, 2, 3, 4, 5};
|
||||
var endBytes = new byte[]{6, 7, 8, 9};
|
||||
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> ArrayHelper.concat(startBytes, null));
|
||||
assertThrows(IllegalArgumentException.class, () -> ArrayHelper.concat(null, endBytes));
|
||||
assertThrows(IllegalArgumentException.class, () -> ArrayHelper.concat(null, null));
|
||||
}
|
||||
}
|
54
cryptography/src/test/java/info/frostfs/sdk/Base58Test.java
Normal file
54
cryptography/src/test/java/info/frostfs/sdk/Base58Test.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
package info.frostfs.sdk;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class Base58Test {
|
||||
private static final String WIF = "L1YS4myg3xHPvi3FHeLaEt7G8upwJaWL5YLV7huviuUtXFpzBMqZ";
|
||||
private static final byte[] DECODE = new byte[]{
|
||||
-128, -128, -5, 30, -36, -118, 85, -67, -6, 81, 43, 93, -38, 106, 21, -88, 127, 15, 125, -79, -17, -40, 77,
|
||||
-15, 122, -88, 72, 109, -47, 125, -80, -40, -38, 1
|
||||
};
|
||||
|
||||
@Test
|
||||
void base58DecodeEncode() {
|
||||
//When + Then
|
||||
assertEquals(WIF, Base58.base58CheckEncode(Base58.base58CheckDecode(WIF)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void base58Decode_success() {
|
||||
//When
|
||||
var decode = Base58.base58CheckDecode(WIF);
|
||||
|
||||
//Then
|
||||
assertThat(decode).hasSize(34).containsExactly(DECODE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void base58Decode_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> Base58.base58CheckDecode(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> Base58.base58CheckDecode(""));
|
||||
assertThrows(IllegalArgumentException.class, () -> Base58.base58CheckDecode("WIF"));
|
||||
assertThrows(IllegalArgumentException.class, () -> Base58.base58CheckDecode("fh"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void base58Encode_success() {
|
||||
//When
|
||||
var encode = Base58.base58CheckEncode(DECODE);
|
||||
|
||||
//Then
|
||||
assertEquals(WIF, encode);
|
||||
}
|
||||
|
||||
@Test
|
||||
void base58Encode_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> Base58.base58CheckEncode(null));
|
||||
}
|
||||
}
|
110
cryptography/src/test/java/info/frostfs/sdk/HelperTest.java
Normal file
110
cryptography/src/test/java/info/frostfs/sdk/HelperTest.java
Normal file
|
@ -0,0 +1,110 @@
|
|||
package info.frostfs.sdk;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class HelperTest {
|
||||
|
||||
@Test
|
||||
void getRipemd160_success() {
|
||||
//Given
|
||||
var value = new byte[]{1, 2, 3, 4, 5};
|
||||
var expected = new byte[]
|
||||
{-21, -126, 92, 75, 36, -12, 37, 7, 122, 6, 124, -61, -66, -12, 87, 120, 63, 90, -41, 5};
|
||||
//When
|
||||
var result = Helper.getRipemd160(value);
|
||||
|
||||
//Then
|
||||
assertThat(result).hasSize(20).containsExactly(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRipemd160_givenParamIsNull() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> Helper.getRipemd160(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRipemd160_givenParamsIsEmpty() {
|
||||
//Given
|
||||
var value = new byte[]{};
|
||||
var expected = new byte[]
|
||||
{-100, 17, -123, -91, -59, -23, -4, 84, 97, 40, 8, -105, 126, -24, -11, 72, -78, 37, -115, 49};
|
||||
//When
|
||||
var result = Helper.getRipemd160(value);
|
||||
|
||||
//Then
|
||||
assertThat(result).hasSize(20).containsExactly(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSha256Instance() {
|
||||
//When
|
||||
var result = Helper.getSha256Instance();
|
||||
|
||||
//Then
|
||||
assertEquals("SHA-256", result.getAlgorithm());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSha256_bytes_success() {
|
||||
//Given
|
||||
var value = new byte[]{1, 2, 3, 4, 5};
|
||||
var expected = new byte[]{
|
||||
116, -8, 31, -31, 103, -39, -101, 76, -76, 29, 109, 12, -51, -88, 34, 120, -54, -18, -97, 62, 47, 37,
|
||||
-43, -27, -93, -109, 111, -13, -36, -20, 96, -48
|
||||
};
|
||||
|
||||
//When
|
||||
var result = Helper.getSha256(value);
|
||||
|
||||
//Then
|
||||
assertThat(result).hasSize(32).containsExactly(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSha256_bytes_givenParamIsNull() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> Helper.getSha256((byte[]) null));
|
||||
assertThrows(IllegalArgumentException.class, () -> Helper.getSha256((Message) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSha256_bytes_givenParamsIsEmpty() {
|
||||
//Given
|
||||
var value = new byte[]{};
|
||||
var expected = new byte[]{
|
||||
-29, -80, -60, 66, -104, -4, 28, 20, -102, -5, -12, -56, -103, 111, -71, 36, 39, -82, 65, -28, 100,
|
||||
-101, -109, 76, -92, -107, -103, 27, 120, 82, -72, 85
|
||||
};
|
||||
|
||||
//When
|
||||
var result = Helper.getSha256(value);
|
||||
|
||||
//Then
|
||||
assertThat(result).hasSize(32).containsExactly(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHexString_success() {
|
||||
//Given
|
||||
var value = new byte[]{1, 2, 3, 4, 5};
|
||||
|
||||
//When
|
||||
var result = Helper.getHexString(value);
|
||||
|
||||
//Then
|
||||
assertEquals("0102030405", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHexString_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> Helper.getHexString(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> Helper.getHexString(new byte[]{}));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package info.frostfs.sdk;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class KeyExtensionTest {
|
||||
private static final String WIF = "L1YS4myg3xHPvi3FHeLaEt7G8upwJaWL5YLV7huviuUtXFpzBMqZ";
|
||||
private static final String OWNER_ID = "NVxUSpEEJzYXZZtUs18PrJTD9QZkLLNQ8S";
|
||||
private static final byte[] PRIVATE_KEY = new byte[]{
|
||||
-128, -5, 30, -36, -118, 85, -67, -6, 81, 43, 93, -38, 106, 21, -88, 127, 15, 125, -79, -17, -40, 77, -15,
|
||||
122, -88, 72, 109, -47, 125, -80, -40, -38
|
||||
};
|
||||
private static final byte[] PUBLIC_KEY = new byte[]{
|
||||
3, 80, -111, 65, 23, 36, -4, -69, 80, 102, 98, -13, 13, -79, 24, 126, -116, 90, 56, 44, 127, 106, -125, 99,
|
||||
-48, -94, 104, 81, 120, -110, 30, 80, 70
|
||||
};
|
||||
private static final byte[] UNCOMPRESSED_PUBLIC_KEY = new byte[]{
|
||||
4, 80, -111, 65, 23, 36, -4, -69, 80, 102, 98, -13, 13, -79, 24, 126, -116, 90, 56, 44, 127, 106, -125, 99,
|
||||
-48, -94, 104, 81, 120, -110, 30, 80, 70, 76, -18, 53, -9, 79, -8, -25, -69, 12, 89, -103, 15, 126, 118,
|
||||
-68, -73, 65, -57, -26, 75, 4, -51, -40, -20, 75, 89, -59, 111, 96, -80, 56, 13
|
||||
};
|
||||
|
||||
@Test
|
||||
void getPrivateKeyFromWIF_success() {
|
||||
//When
|
||||
var privateKey = KeyExtension.getPrivateKeyFromWIF(WIF);
|
||||
|
||||
//Then
|
||||
assertThat(privateKey).hasSize(32).containsExactly(PRIVATE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPrivateKeyFromWIF_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getPrivateKeyFromWIF(""));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getPrivateKeyFromWIF(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadPublicKey_success() {
|
||||
//When
|
||||
var publicKey = KeyExtension.loadPublicKey(PRIVATE_KEY);
|
||||
|
||||
//Then
|
||||
assertThat(publicKey).hasSize(33).containsExactly(PUBLIC_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadPublicKey_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.loadPublicKey(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.loadPublicKey(new byte[]{}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadPrivateKey_success() {
|
||||
//When
|
||||
var privateKey = KeyExtension.loadPrivateKey(PRIVATE_KEY);
|
||||
|
||||
//Then
|
||||
assertThat(privateKey.getEncoded()).hasSize(67).endsWith(PRIVATE_KEY);
|
||||
assertEquals("EC", privateKey.getAlgorithm());
|
||||
assertEquals("PKCS#8", privateKey.getFormat());
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadPrivateKey_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.loadPrivateKey(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.loadPrivateKey(new byte[]{}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPublicKeyFromBytes_success() {
|
||||
//When
|
||||
var publicKey = KeyExtension.getPublicKeyFromBytes(PUBLIC_KEY);
|
||||
|
||||
//Then
|
||||
assertThat(publicKey.getEncoded()).hasSize(91).endsWith(UNCOMPRESSED_PUBLIC_KEY);
|
||||
assertEquals("EC", publicKey.getAlgorithm());
|
||||
assertEquals("X.509", publicKey.getFormat());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPublicKeyFromBytes_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getPublicKeyFromBytes(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getPublicKeyFromBytes(new byte[]{}));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getPublicKeyFromBytes(PRIVATE_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getScriptHash_success() {
|
||||
//Given
|
||||
var expected = new byte[]{
|
||||
110, 42, -125, -76, -25, -44, -94, 22, -98, 117, -100, -5, 103, 74, -128, -51, 37, -116, -102, 71
|
||||
};
|
||||
|
||||
//When
|
||||
var hash = KeyExtension.getScriptHash(PUBLIC_KEY);
|
||||
|
||||
//Then
|
||||
assertThat(hash).hasSize(20).containsExactly(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getScriptHash_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getScriptHash(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getScriptHash(new byte[]{}));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.getScriptHash(PRIVATE_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
void publicKeyToAddress_success() {
|
||||
//When
|
||||
var address = KeyExtension.publicKeyToAddress(PUBLIC_KEY);
|
||||
|
||||
//Then
|
||||
assertEquals(OWNER_ID, address);
|
||||
}
|
||||
|
||||
@Test
|
||||
void publicKeyToAddress_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.publicKeyToAddress(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.publicKeyToAddress(new byte[]{}));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.publicKeyToAddress(PRIVATE_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
void compress_success() {
|
||||
//When
|
||||
var publicKey = KeyExtension.compress(UNCOMPRESSED_PUBLIC_KEY);
|
||||
|
||||
//Then
|
||||
assertThat(publicKey).hasSize(33).containsExactly(PUBLIC_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void compress_wrong() {
|
||||
//When + Then
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.compress(null));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.compress(new byte[]{}));
|
||||
assertThrows(IllegalArgumentException.class, () -> KeyExtension.compress(PUBLIC_KEY));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue