Updated and fixed JavaDoc
This commit is contained in:
parent
6be8d51f6d
commit
1eb6851798
@ -44,7 +44,7 @@ import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this class if you want to create a Bitmessage client.
|
* Use this class if you want to create a Bitmessage client.
|
||||||
* <p/>
|
* <p>
|
||||||
* You'll need the Builder to create a BitmessageContext, and set the following properties:
|
* You'll need the Builder to create a BitmessageContext, and set the following properties:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>addressRepo</li>
|
* <li>addressRepo</li>
|
||||||
@ -55,8 +55,10 @@ import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
|||||||
* <li>streams</li>
|
* <li>streams</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* The default implementations in the different module builds can be used.
|
* The default implementations in the different module builds can be used.
|
||||||
* <p/>
|
* </p>
|
||||||
|
* <p>
|
||||||
* The port defaults to 8444 (the default Bitmessage port)
|
* The port defaults to 8444 (the default Bitmessage port)
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class BitmessageContext {
|
public class BitmessageContext {
|
||||||
public static final int CURRENT_VERSION = 3;
|
public static final int CURRENT_VERSION = 3;
|
||||||
|
@ -35,8 +35,9 @@ import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
|||||||
* The internal context should normally only be used for port implementations. If you need it in your client
|
* The internal context should normally only be used for port implementations. If you need it in your client
|
||||||
* implementation, you're either doing something wrong, something very weird, or the BitmessageContext should
|
* implementation, you're either doing something wrong, something very weird, or the BitmessageContext should
|
||||||
* get extended.
|
* get extended.
|
||||||
* <p/>
|
* <p>
|
||||||
* On the other hand, if you need the BitmessageContext in a port implementation, the same thing might apply.
|
* On the other hand, if you need the BitmessageContext in a port implementation, the same thing might apply.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class InternalContext {
|
public class InternalContext {
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(InternalContext.class);
|
private final static Logger LOG = LoggerFactory.getLogger(InternalContext.class);
|
||||||
|
@ -158,7 +158,7 @@ public class BitmessageAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the private key used to decrypt Pubkey objects (for v4 addresses) and broadcasts.
|
* @return the private key used to decrypt Pubkey objects (for v4 addresses) and broadcasts.
|
||||||
*/
|
*/
|
||||||
public byte[] getPublicDecryptionKey() {
|
public byte[] getPublicDecryptionKey() {
|
||||||
return publicDecryptionKey;
|
return publicDecryptionKey;
|
||||||
|
@ -47,11 +47,11 @@ public class CryptoBox implements Streamable {
|
|||||||
private final byte[] mac;
|
private final byte[] mac;
|
||||||
private byte[] encrypted;
|
private byte[] encrypted;
|
||||||
|
|
||||||
public CryptoBox(Streamable data, byte[] encryptionKey) {
|
public CryptoBox(Streamable data, byte[] encryptionKey) throws IOException {
|
||||||
this(data, Security.keyToPoint(encryptionKey));
|
this(data, Security.keyToPoint(encryptionKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CryptoBox(Streamable data, ECPoint K) {
|
public CryptoBox(Streamable data, ECPoint K) throws IOException {
|
||||||
curveType = 0x02CA;
|
curveType = 0x02CA;
|
||||||
|
|
||||||
// 1. The destination public key is called K.
|
// 1. The destination public key is called K.
|
||||||
@ -71,7 +71,7 @@ public class CryptoBox implements Streamable {
|
|||||||
byte[] key_m = Arrays.copyOfRange(H, 32, 64);
|
byte[] key_m = Arrays.copyOfRange(H, 32, 64);
|
||||||
// 7. Pad the input text to a multiple of 16 bytes, in accordance to PKCS7.
|
// 7. Pad the input text to a multiple of 16 bytes, in accordance to PKCS7.
|
||||||
// 8. Encrypt the data with AES-256-CBC, using IV as initialization vector, key_e as encryption key and the padded input text as payload. Call the output cipher text.
|
// 8. Encrypt the data with AES-256-CBC, using IV as initialization vector, key_e as encryption key and the padded input text as payload. Call the output cipher text.
|
||||||
encrypted = crypt(true, Bytes.from(data), key_e);
|
encrypted = crypt(true, Encode.bytes(data), key_e);
|
||||||
// 9. Calculate a 32 byte MAC with HMACSHA256, using key_m as salt and IV + R + cipher text as data. Call the output MAC.
|
// 9. Calculate a 32 byte MAC with HMACSHA256, using key_m as salt and IV + R + cipher text as data. Call the output MAC.
|
||||||
mac = calculateMac(key_m);
|
mac = calculateMac(key_m);
|
||||||
|
|
||||||
@ -99,6 +99,9 @@ public class CryptoBox implements Streamable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param privateKey a private key, typically should be 32 bytes long
|
||||||
|
* @return an InputStream yielding the decrypted data
|
||||||
|
* @throws DecryptionFailedException if the payload can't be decrypted using this private key
|
||||||
* @see <a href='https://bitmessage.org/wiki/Encryption#Decryption'>https://bitmessage.org/wiki/Encryption#Decryption</a>
|
* @see <a href='https://bitmessage.org/wiki/Encryption#Decryption'>https://bitmessage.org/wiki/Encryption#Decryption</a>
|
||||||
*/
|
*/
|
||||||
public InputStream decrypt(byte[] privateKey) throws DecryptionFailedException {
|
public InputStream decrypt(byte[] privateKey) throws DecryptionFailedException {
|
||||||
|
@ -50,7 +50,7 @@ public class GetPubkey extends ObjectPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of bytes that represent either the ripe, or the tag of an address, depending on the
|
* @return an array of bytes that represent either the ripe, or the tag of an address, depending on the
|
||||||
* address version.
|
* address version.
|
||||||
*/
|
*/
|
||||||
public byte[] getRipeTag() {
|
public byte[] getRipeTag() {
|
||||||
|
@ -50,7 +50,7 @@ public abstract class ObjectPayload implements Streamable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ECDSA signature which, as of protocol v3, covers the object header starting with the time,
|
* @return the ECDSA signature which, as of protocol v3, covers the object header starting with the time,
|
||||||
* appended with the data described in this table down to the extra_bytes. Therefore, this must
|
* appended with the data described in this table down to the extra_bytes. Therefore, this must
|
||||||
* be checked and set in the {@link ObjectMessage} object.
|
* be checked and set in the {@link ObjectMessage} object.
|
||||||
*/
|
*/
|
||||||
|
@ -31,12 +31,15 @@ public class Label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RGBA representation for the color.
|
* @return RGBA representation for the color.
|
||||||
*/
|
*/
|
||||||
public int getColor() {
|
public int getColor() {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param color RGBA representation for the color.
|
||||||
|
*/
|
||||||
public void setColor(int color) {
|
public void setColor(int color) {
|
||||||
this.color = color;
|
this.color = color;
|
||||||
}
|
}
|
||||||
@ -50,14 +53,14 @@ public class Label {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Object id) {
|
public void setId(Object id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -26,7 +26,7 @@ public interface AddressRepository {
|
|||||||
BitmessageAddress findIdentity(byte[] ripeOrTag);
|
BitmessageAddress findIdentity(byte[] ripeOrTag);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all Bitmessage addresses that belong to this user, i.e. have a private key.
|
* @return all Bitmessage addresses that belong to this user, i.e. have a private key.
|
||||||
*/
|
*/
|
||||||
List<BitmessageAddress> getIdentities();
|
List<BitmessageAddress> getIdentities();
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ public interface AddressRepository {
|
|||||||
List<BitmessageAddress> getSubscriptions(long broadcastVersion);
|
List<BitmessageAddress> getSubscriptions(long broadcastVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all Bitmessage addresses that have no private key.
|
* @return all Bitmessage addresses that have no private key.
|
||||||
*/
|
*/
|
||||||
List<BitmessageAddress> getContacts();
|
List<BitmessageAddress> getContacts();
|
||||||
|
|
||||||
|
@ -29,9 +29,8 @@ import static java.util.Arrays.copyOfRange;
|
|||||||
* @author Christian Basler: I removed some dependencies to the BitcoinJ code so it can be used here more easily.
|
* @author Christian Basler: I removed some dependencies to the BitcoinJ code so it can be used here more easily.
|
||||||
*/
|
*/
|
||||||
public class Base58 {
|
public class Base58 {
|
||||||
private static char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
|
|
||||||
|
|
||||||
private static final int[] INDEXES = new int[128];
|
private static final int[] INDEXES = new int[128];
|
||||||
|
private static char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < INDEXES.length; i++) {
|
for (int i = 0; i < INDEXES.length; i++) {
|
||||||
@ -44,6 +43,9 @@ public class Base58 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes the given bytes in base58. No checksum is appended.
|
* Encodes the given bytes in base58. No checksum is appended.
|
||||||
|
*
|
||||||
|
* @param input to encode
|
||||||
|
* @return base58 encoded input
|
||||||
*/
|
*/
|
||||||
public static String encode(byte[] input) {
|
public static String encode(byte[] input) {
|
||||||
if (input.length == 0) {
|
if (input.length == 0) {
|
||||||
|
@ -38,6 +38,9 @@ public class Bytes {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases nonce by value, which is used as an unsigned byte value.
|
* Increases nonce by value, which is used as an unsigned byte value.
|
||||||
|
*
|
||||||
|
* @param nonce an unsigned number
|
||||||
|
* @param value to be added to nonce
|
||||||
*/
|
*/
|
||||||
public static void inc(byte[] nonce, byte value) {
|
public static void inc(byte[] nonce, byte value) {
|
||||||
int i = nonce.length - 1;
|
int i = nonce.length - 1;
|
||||||
@ -54,7 +57,7 @@ public class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a < b.
|
* @return true if a < b.
|
||||||
*/
|
*/
|
||||||
public static boolean lt(byte[] a, byte[] b) {
|
public static boolean lt(byte[] a, byte[] b) {
|
||||||
byte[] max = (a.length > b.length ? a : b);
|
byte[] max = (a.length > b.length ? a : b);
|
||||||
@ -73,7 +76,7 @@ public class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a < b, where the first [size] bytes are used as the numbers to check.
|
* @return true if a < b, where the first [size] bytes are used as the numbers to check.
|
||||||
*/
|
*/
|
||||||
public static boolean lt(byte[] a, byte[] b, int size) {
|
public static boolean lt(byte[] a, byte[] b, int size) {
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
@ -91,7 +94,7 @@ public class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new byte array of length, left-padded with '0'.
|
* @return a new byte array of length, left-padded with '0'.
|
||||||
*/
|
*/
|
||||||
public static byte[] expand(byte[] source, int size) {
|
public static byte[] expand(byte[] source, int size) {
|
||||||
byte[] result = new byte[size];
|
byte[] result = new byte[size];
|
||||||
@ -100,7 +103,7 @@ public class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new byte array containing the first <em>size</em> bytes of the given array.
|
* @return a new byte array containing the first <em>size</em> bytes of the given array.
|
||||||
*/
|
*/
|
||||||
public static byte[] truncate(byte[] source, int size) {
|
public static byte[] truncate(byte[] source, int size) {
|
||||||
byte[] result = new byte[size];
|
byte[] result = new byte[size];
|
||||||
@ -109,7 +112,7 @@ public class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the byte array that hex represents. This is meant for test use and should be rewritten if used in
|
* @return the byte array that hex represents. This is meant for test use and should be rewritten if used in
|
||||||
* production code.
|
* production code.
|
||||||
*/
|
*/
|
||||||
public static byte[] fromHex(String hex) {
|
public static byte[] fromHex(String hex) {
|
||||||
@ -136,7 +139,7 @@ public class Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of leading '0' of a byte array.
|
* @return the number of leading '0' of a byte array.
|
||||||
*/
|
*/
|
||||||
public static int numberOfLeadingZeros(byte[] bytes) {
|
public static int numberOfLeadingZeros(byte[] bytes) {
|
||||||
int i;
|
int i;
|
||||||
@ -145,24 +148,4 @@ public class Bytes {
|
|||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a copy of bytes with leading zeroes stripped.
|
|
||||||
*/
|
|
||||||
public static byte[] stripLeadingZeros(byte[] bytes) {
|
|
||||||
return Arrays.copyOfRange(bytes, numberOfLeadingZeros(bytes), bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the byte array of the serialized data.
|
|
||||||
*/
|
|
||||||
public static byte[] from(Streamable data) {
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
data.write(out);
|
|
||||||
return out.toByteArray();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,11 @@ public class Collections {
|
|||||||
private final static Random RANDOM = new Random();
|
private final static Random RANDOM = new Random();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a random subset of the given collection, or a copy of the collection if it's not larger than count.
|
* @param count the number of elements to return (if possible)
|
||||||
* The randomness
|
* @param collection the collection to take samples from
|
||||||
|
* @return a random subset of the given collection, or a copy of the collection if it's not larger than count. The
|
||||||
|
* result is by no means securely random, but should be random enough so not the same objects get selected over
|
||||||
|
* and over again.
|
||||||
*/
|
*/
|
||||||
public static <T> List<T> selectRandom(int count, Collection<T> collection) {
|
public static <T> List<T> selectRandom(int count, Collection<T> collection) {
|
||||||
ArrayList<T> result = new ArrayList<>(count);
|
ArrayList<T> result = new ArrayList<>(count);
|
||||||
|
@ -112,7 +112,9 @@ public class Encode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of bytes representing the given streamable object.
|
* @param streamable the object to be serialized
|
||||||
|
* @return an array of bytes representing the given streamable object.
|
||||||
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public static byte[] bytes(Streamable streamable) throws IOException {
|
public static byte[] bytes(Streamable streamable) throws IOException {
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
@ -121,8 +123,10 @@ public class Encode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bytes of the given streamable object, 0-padded such that the final
|
* @param streamable the object to be serialized
|
||||||
* length is x*padding.
|
* @param padding the result will be padded such that its length is a multiple of <em>padding</em>
|
||||||
|
* @return the bytes of the given {@link Streamable} object, 0-padded such that the final length is x*padding.
|
||||||
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
public static byte[] bytes(Streamable streamable, int padding) throws IOException {
|
public static byte[] bytes(Streamable streamable, int padding) throws IOException {
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
|
@ -40,7 +40,8 @@ import java.security.spec.KeySpec;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides some methods to help with hashing and encryption.
|
* Provides some methods to help with hashing and encryption. All randoms are created using {@link SecureRandom},
|
||||||
|
* which should be secure enough.
|
||||||
*/
|
*/
|
||||||
public class Security {
|
public class Security {
|
||||||
public static final Logger LOG = LoggerFactory.getLogger(Security.class);
|
public static final Logger LOG = LoggerFactory.getLogger(Security.class);
|
||||||
@ -52,10 +53,26 @@ public class Security {
|
|||||||
java.security.Security.addProvider(new BouncyCastleProvider());
|
java.security.Security.addProvider(new BouncyCastleProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method to calculate SHA-512 hashes. Please note that a new {@link MessageDigest} object is created at
|
||||||
|
* each call (to ensure thread safety), so you shouldn't use this if you need to do many hash calculations in
|
||||||
|
* success on the same thread.
|
||||||
|
*
|
||||||
|
* @param data to get hashed
|
||||||
|
* @return SHA-512 hash of data
|
||||||
|
*/
|
||||||
public static byte[] sha512(byte[]... data) {
|
public static byte[] sha512(byte[]... data) {
|
||||||
return hash("SHA-512", data);
|
return hash("SHA-512", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method to calculate doubleSHA-512 hashes. Please note that a new {@link MessageDigest} object is created
|
||||||
|
* at each call (to ensure thread safety), so you shouldn't use this if you need to do many hash calculations in
|
||||||
|
* success on the same thread.
|
||||||
|
*
|
||||||
|
* @param data to get hashed
|
||||||
|
* @return SHA-512 hash of data
|
||||||
|
*/
|
||||||
public static byte[] doubleSha512(byte[]... data) {
|
public static byte[] doubleSha512(byte[]... data) {
|
||||||
MessageDigest mda = md("SHA-512");
|
MessageDigest mda = md("SHA-512");
|
||||||
for (byte[] d : data) {
|
for (byte[] d : data) {
|
||||||
@ -64,33 +81,97 @@ public class Security {
|
|||||||
return mda.digest(mda.digest());
|
return mda.digest(mda.digest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method to calculate double SHA-512 hashes. This method allows to only use a part of the available bytes
|
||||||
|
* to use for the hash calculation.
|
||||||
|
* <p>
|
||||||
|
* Please note that a new {@link MessageDigest} object is created at each call (to ensure thread safety), so you
|
||||||
|
* shouldn't use this if you need to do many hash calculations in short order on the same thread.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param data to get hashed
|
||||||
|
* @param length number of bytes to be taken into account
|
||||||
|
* @return SHA-512 hash of data
|
||||||
|
*/
|
||||||
public static byte[] doubleSha512(byte[] data, int length) {
|
public static byte[] doubleSha512(byte[] data, int length) {
|
||||||
MessageDigest mda = md("SHA-512");
|
MessageDigest mda = md("SHA-512");
|
||||||
mda.update(data, 0, length);
|
mda.update(data, 0, length);
|
||||||
return mda.digest(mda.digest());
|
return mda.digest(mda.digest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method to calculate RIPEMD-160 hashes. Supplying multiple byte arrays has the same result as a
|
||||||
|
* concatenation of all arrays, but might perform better.
|
||||||
|
* <p>
|
||||||
|
* Please note that a new {@link MessageDigest} object is created at
|
||||||
|
* each call (to ensure thread safety), so you shouldn't use this if you need to do many hash calculations in short
|
||||||
|
* order on the same thread.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param data to get hashed
|
||||||
|
* @return RIPEMD-160 hash of data
|
||||||
|
*/
|
||||||
public static byte[] ripemd160(byte[]... data) {
|
public static byte[] ripemd160(byte[]... data) {
|
||||||
return hash("RIPEMD160", data);
|
return hash("RIPEMD160", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method to calculate double SHA-256 hashes. This method allows to only use a part of the available bytes
|
||||||
|
* to use for the hash calculation.
|
||||||
|
* <p>
|
||||||
|
* Please note that a new {@link MessageDigest} object is created at
|
||||||
|
* each call (to ensure thread safety), so you shouldn't use this if you need to do many hash calculations in short
|
||||||
|
* order on the same thread.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param data to get hashed
|
||||||
|
* @param length number of bytes to be taken into account
|
||||||
|
* @return SHA-256 hash of data
|
||||||
|
*/
|
||||||
public static byte[] doubleSha256(byte[] data, int length) {
|
public static byte[] doubleSha256(byte[] data, int length) {
|
||||||
MessageDigest mda = md("SHA-256");
|
MessageDigest mda = md("SHA-256");
|
||||||
mda.update(data, 0, length);
|
mda.update(data, 0, length);
|
||||||
return mda.digest(mda.digest());
|
return mda.digest(mda.digest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method to calculate SHA-1 hashes. Supplying multiple byte arrays has the same result as a
|
||||||
|
* concatenation of all arrays, but might perform better.
|
||||||
|
* <p>
|
||||||
|
* Please note that a new {@link MessageDigest} object is created at
|
||||||
|
* each call (to ensure thread safety), so you shouldn't use this if you need to do many hash calculations in short
|
||||||
|
* order on the same thread.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param data to get hashed
|
||||||
|
* @return SHA hash of data
|
||||||
|
*/
|
||||||
public static byte[] sha1(byte[]... data) {
|
public static byte[] sha1(byte[]... data) {
|
||||||
return hash("SHA-1", data);
|
return hash("SHA-1", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param length number of bytes to return
|
||||||
|
* @return an array of the given size containing random bytes
|
||||||
|
*/
|
||||||
public static byte[] randomBytes(int length) {
|
public static byte[] randomBytes(int length) {
|
||||||
byte[] result = new byte[length];
|
byte[] result = new byte[length];
|
||||||
RANDOM.nextBytes(result);
|
RANDOM.nextBytes(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void doProofOfWork(ObjectMessage object, ProofOfWorkEngine worker, long nonceTrialsPerByte, long extraBytes) {
|
/**
|
||||||
|
* Calculates the proof of work. This might take a long time, depending on the hardware, message size and time to
|
||||||
|
* live.
|
||||||
|
*
|
||||||
|
* @param object to do the proof of work for
|
||||||
|
* @param worker doing the actual proof of work
|
||||||
|
* @param nonceTrialsPerByte difficulty
|
||||||
|
* @param extraBytes bytes to add to the object size (makes it more difficult to send small messages)
|
||||||
|
*/
|
||||||
|
public static void doProofOfWork(ObjectMessage object, ProofOfWorkEngine worker, long nonceTrialsPerByte,
|
||||||
|
long extraBytes) {
|
||||||
try {
|
try {
|
||||||
if (nonceTrialsPerByte < 1000) nonceTrialsPerByte = 1000;
|
if (nonceTrialsPerByte < 1000) nonceTrialsPerByte = 1000;
|
||||||
if (extraBytes < 1000) extraBytes = 1000;
|
if (extraBytes < 1000) extraBytes = 1000;
|
||||||
@ -107,9 +188,13 @@ public class Security {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws InsufficientProofOfWorkException if proof of work doesn't check out
|
* @param object to be checked
|
||||||
|
* @param nonceTrialsPerByte difficulty
|
||||||
|
* @param extraBytes bytes to add to the object size
|
||||||
|
* @throws InsufficientProofOfWorkException if proof of work doesn't check out (makes it more difficult to send small messages)
|
||||||
*/
|
*/
|
||||||
public static void checkProofOfWork(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) throws IOException {
|
public static void checkProofOfWork(ObjectMessage object, long nonceTrialsPerByte, long extraBytes)
|
||||||
|
throws IOException {
|
||||||
byte[] target = getProofOfWorkTarget(object, nonceTrialsPerByte, extraBytes);
|
byte[] target = getProofOfWorkTarget(object, nonceTrialsPerByte, extraBytes);
|
||||||
byte[] value = Security.doubleSha512(object.getNonce(), getInitialHash(object));
|
byte[] value = Security.doubleSha512(object.getNonce(), getInitialHash(object));
|
||||||
if (Bytes.lt(target, value, 8)) {
|
if (Bytes.lt(target, value, 8)) {
|
||||||
@ -146,6 +231,13 @@ public class Security {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the MAC for a message (data)
|
||||||
|
*
|
||||||
|
* @param key_m the symmetric key used
|
||||||
|
* @param data the message data to calculate the MAC for
|
||||||
|
* @return the MAC
|
||||||
|
*/
|
||||||
public static byte[] mac(byte[] key_m, byte[] data) {
|
public static byte[] mac(byte[] key_m, byte[] data) {
|
||||||
try {
|
try {
|
||||||
Mac mac = Mac.getInstance("HmacSHA256", "BC");
|
Mac mac = Mac.getInstance("HmacSHA256", "BC");
|
||||||
@ -156,6 +248,18 @@ public class Security {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new public key fom given private keys.
|
||||||
|
*
|
||||||
|
* @param version of the public key / address
|
||||||
|
* @param stream of the address
|
||||||
|
* @param privateSigningKey private key used for signing
|
||||||
|
* @param privateEncryptionKey private key used for encryption
|
||||||
|
* @param nonceTrialsPerByte proof of work difficulty
|
||||||
|
* @param extraBytes bytes to add for the proof of work (make it harder for small messages)
|
||||||
|
* @param features of the address
|
||||||
|
* @return a public key object
|
||||||
|
*/
|
||||||
public static Pubkey createPubkey(long version, long stream, byte[] privateSigningKey, byte[] privateEncryptionKey,
|
public static Pubkey createPubkey(long version, long stream, byte[] privateSigningKey, byte[] privateEncryptionKey,
|
||||||
long nonceTrialsPerByte, long extraBytes, Pubkey.Feature... features) {
|
long nonceTrialsPerByte, long extraBytes, Pubkey.Feature... features) {
|
||||||
return Factory.createPubkey(version, stream,
|
return Factory.createPubkey(version, stream,
|
||||||
@ -164,10 +268,18 @@ public class Security {
|
|||||||
nonceTrialsPerByte, extraBytes, features);
|
nonceTrialsPerByte, extraBytes, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param privateKey private key as byte array
|
||||||
|
* @return a public key corresponding to the given private key
|
||||||
|
*/
|
||||||
public static ECPoint createPublicKey(byte[] privateKey) {
|
public static ECPoint createPublicKey(byte[] privateKey) {
|
||||||
return EC_CURVE_PARAMETERS.getG().multiply(keyToBigInt(privateKey)).normalize();
|
return EC_CURVE_PARAMETERS.getG().multiply(keyToBigInt(privateKey)).normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param privateKey private key as byte array
|
||||||
|
* @return a big integer representation (unsigned) of the given bytes
|
||||||
|
*/
|
||||||
public static BigInteger keyToBigInt(byte[] privateKey) {
|
public static BigInteger keyToBigInt(byte[] privateKey) {
|
||||||
return new BigInteger(1, privateKey);
|
return new BigInteger(1, privateKey);
|
||||||
}
|
}
|
||||||
@ -185,7 +297,13 @@ public class Security {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSignatureValid(byte[] bytesToSign, byte[] signature, Pubkey pubkey) {
|
/**
|
||||||
|
* @param data to check
|
||||||
|
* @param signature the signature of the message
|
||||||
|
* @param pubkey the sender's public key
|
||||||
|
* @return true if the signature is valid, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean isSignatureValid(byte[] data, byte[] signature, Pubkey pubkey) {
|
||||||
try {
|
try {
|
||||||
ECParameterSpec spec = new ECParameterSpec(
|
ECParameterSpec spec = new ECParameterSpec(
|
||||||
EC_CURVE_PARAMETERS.getCurve(),
|
EC_CURVE_PARAMETERS.getCurve(),
|
||||||
@ -201,13 +319,20 @@ public class Security {
|
|||||||
|
|
||||||
Signature sig = Signature.getInstance("ECDSA", "BC");
|
Signature sig = Signature.getInstance("ECDSA", "BC");
|
||||||
sig.initVerify(publicKey);
|
sig.initVerify(publicKey);
|
||||||
sig.update(bytesToSign);
|
sig.update(data);
|
||||||
return sig.verify(signature);
|
return sig.verify(signature);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the signature of data, using the given private key.
|
||||||
|
*
|
||||||
|
* @param data to be signed
|
||||||
|
* @param privateKey to be used for signing
|
||||||
|
* @return the signature
|
||||||
|
*/
|
||||||
public static byte[] getSignature(byte[] data, ch.dissem.bitmessage.entity.valueobject.PrivateKey privateKey) {
|
public static byte[] getSignature(byte[] data, ch.dissem.bitmessage.entity.valueobject.PrivateKey privateKey) {
|
||||||
try {
|
try {
|
||||||
ECParameterSpec spec = new ECParameterSpec(
|
ECParameterSpec spec = new ECParameterSpec(
|
||||||
@ -231,6 +356,9 @@ public class Security {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a random number of type long
|
||||||
|
*/
|
||||||
public static long randomNonce() {
|
public static long randomNonce() {
|
||||||
return RANDOM.nextLong();
|
return RANDOM.nextLong();
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ public class UnixTime {
|
|||||||
public static final long DAY = 24 * HOUR;
|
public static final long DAY = 24 * HOUR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time in second based Unix time ({@link System#currentTimeMillis()}/1000)
|
* @return the time in second based Unix time ({@link System#currentTimeMillis()}/1000)
|
||||||
*/
|
*/
|
||||||
public static long now() {
|
public static long now() {
|
||||||
return System.currentTimeMillis() / 1000;
|
return System.currentTimeMillis() / 1000;
|
||||||
@ -38,6 +38,9 @@ public class UnixTime {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #now()} + shiftSeconds, but might be more readable.
|
* Same as {@link #now()} + shiftSeconds, but might be more readable.
|
||||||
|
*
|
||||||
|
* @param shiftSeconds number of seconds from now we're interested in
|
||||||
|
* @return the Unix time in shiftSeconds seconds / shiftSeconds seconds ago
|
||||||
*/
|
*/
|
||||||
public static long now(long shiftSeconds) {
|
public static long now(long shiftSeconds) {
|
||||||
return (System.currentTimeMillis() / 1000) + shiftSeconds;
|
return (System.currentTimeMillis() / 1000) + shiftSeconds;
|
||||||
|
Loading…
Reference in New Issue
Block a user