Updated and fixed JavaDoc
This commit is contained in:
		| @@ -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; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user