├── .gitignore ├── README.md ├── build.gradle ├── configure.sh ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main └── java ├── core ├── AddressFormatException.java ├── Base58.java ├── ECKey.java ├── Sha256Hash.java ├── Utils.java └── cryptohash │ ├── Digest.java │ ├── DigestEngine.java │ ├── HashUtil.java │ ├── Keccak256.java │ └── KeccakCore.java └── utils └── UscConversionUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Gradle 2 | .gradle 3 | build 4 | 5 | # IDEA 6 | out 7 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # usc-utils-api 2 | 3 | usc-utils-api is a java api for converting Ulord private key to Ulord-Sidechain private key and vice-versa. 4 | 5 | To use the api, download and copy the [usc-utils-api-1.0-SNAPSHOT-all.jar](https://github.com/UlordChain/usc-utils-api/releases) file into libs directory of the project, 6 | and add the following in build.gradle dependencies section:- 7 | ``` 8 | compile fileTree(dir: 'libs', include: '*.jar') 9 | ``` 10 | 11 | ### Import the UscConversionUtils class 12 | ``` 13 | import utils.UscConversionUtils; 14 | ``` 15 | 16 | ### Call static functions 17 | ``` 18 | //To convert Ulord private key to USC private key 19 | String uscPrivKey = UscConversionUtils.privKeyToUscFormat("UlordPrivateKey"); 20 | 21 | //To get the USC address 22 | String address = UscConversionUtils.getUscAddress("uscPrivKey").toLowerCase(); 23 | 24 | //To get USC Public key 25 | String uscPubKey = UscConversionUtils.getUscPubKey("uscPrivKey").toLowerCase(); 26 | 27 | //To convert USC private key to Ulord private key 28 | //First Parameter can be either ("main", "test") 29 | //@main to generate private key for mainnet. 30 | //@test to generate Private key for testnet. 31 | String ulordPrivateKey = UscConversionUtils.getUldPrivateKey("test","UscPrivateKey") 32 | ``` 33 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | version '1.0-SNAPSHOT' 2 | 3 | apply plugin: 'java' 4 | 5 | sourceCompatibility = 1.8 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | compile 'com.madgag.spongycastle:core:1.58.0.0' 13 | implementation 'com.google.guava:guava:24.0-android' 14 | testCompile group: 'junit', name: 'junit', version: '4.12' 15 | } 16 | 17 | task fatJar(type: Jar) { 18 | classifier = 'all' 19 | from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 20 | with jar 21 | } -------------------------------------------------------------------------------- /configure.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | unamestr=`uname` 4 | 5 | 6 | function downloadJar(){ 7 | platform 8 | if [ ! -d ./libs ]; then 9 | mkdir ./libs 10 | fi 11 | 12 | 13 | curl -o ./libs/ulordj-thin-0.0.1-usc-1-bundled.jar -L https://github.com/UlordChain/ulordj-thin/releases/download/ulordj-thin-0.0.1/ulordj-thin-0.0.1-usc-1-bundled.jar; 14 | 15 | } 16 | 17 | function platform() { 18 | if [[ "$unamestr" == 'Linux' ]]; then 19 | PLATFORM='linux' 20 | elif [[ "$unamestr" == 'Darwin' ]]; then 21 | PLATFORM='mac' 22 | elif [[ "$unamestr" =~ 'MINGW' ]]; then 23 | PLATFORM='windows' 24 | else 25 | echo -e "\e[1m\e[31m[ ERROR ]\e[0m UNRECOGNIZED PLATFORM" 26 | exit 2 27 | fi 28 | } 29 | 30 | downloadJar 31 | 32 | exit 0 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlordChain/usc-utils-api/671606cf0830244ce2f79812ba84120b277ec0ab/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'usc-utils-api' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/core/AddressFormatException.java: -------------------------------------------------------------------------------- 1 | package core; 2 | 3 | @SuppressWarnings("serial") 4 | public class AddressFormatException extends IllegalArgumentException { 5 | public AddressFormatException() { 6 | super(); 7 | } 8 | 9 | public AddressFormatException(String message) { 10 | super(message); 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/java/core/Base58.java: -------------------------------------------------------------------------------- 1 | package core; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Base58 { 6 | public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); 7 | private static final char ENCODED_ZERO = ALPHABET[0]; 8 | private static final int[] INDEXES = new int[128]; 9 | 10 | static { 11 | Arrays.fill(INDEXES, -1); 12 | for (int i = 0; i < ALPHABET.length; i++) { 13 | INDEXES[ALPHABET[i]] = i; 14 | } 15 | } 16 | 17 | public static String encode(byte[] input) { 18 | if (input.length == 0) { 19 | return ""; 20 | } 21 | // Count leading zeros. 22 | int zeros = 0; 23 | while (zeros < input.length && input[zeros] == 0) { 24 | ++zeros; 25 | } 26 | // Convert base-256 digits to base-58 digits (plus conversion to ASCII characters) 27 | input = Arrays.copyOf(input, input.length); // since we modify it in-place 28 | char[] encoded = new char[input.length * 2]; // upper bound 29 | int outputStart = encoded.length; 30 | for (int inputStart = zeros; inputStart < input.length; ) { 31 | encoded[--outputStart] = ALPHABET[divmod(input, inputStart, 256, 58)]; 32 | if (input[inputStart] == 0) { 33 | ++inputStart; // optimization - skip leading zeros 34 | } 35 | } 36 | // Preserve exactly as many leading encoded zeros in output as there were leading zeros in input. 37 | while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) { 38 | ++outputStart; 39 | } 40 | while (--zeros >= 0) { 41 | encoded[--outputStart] = ENCODED_ZERO; 42 | } 43 | // Return encoded string (including encoded leading zeros). 44 | return new String(encoded, outputStart, encoded.length - outputStart); 45 | } 46 | 47 | public static byte[] decode(String input) throws AddressFormatException { 48 | if (input.length() == 0) { 49 | return new byte[0]; 50 | } 51 | // Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits). 52 | byte[] input58 = new byte[input.length()]; 53 | for (int i = 0; i < input.length(); ++i) { 54 | char c = input.charAt(i); 55 | int digit = c < 128 ? INDEXES[c] : -1; 56 | if (digit < 0) { 57 | throw new AddressFormatException("Illegal character " + c + " at position " + i); 58 | } 59 | input58[i] = (byte) digit; 60 | } 61 | // Count leading zeros. 62 | int zeros = 0; 63 | while (zeros < input58.length && input58[zeros] == 0) { 64 | ++zeros; 65 | } 66 | // Convert base-58 digits to base-256 digits. 67 | byte[] decoded = new byte[input.length()]; 68 | int outputStart = decoded.length; 69 | for (int inputStart = zeros; inputStart < input58.length; ) { 70 | decoded[--outputStart] = divmod(input58, inputStart, 58, 256); 71 | if (input58[inputStart] == 0) { 72 | ++inputStart; // optimization - skip leading zeros 73 | } 74 | } 75 | // Ignore extra leading zeroes that were added during the calculation. 76 | while (outputStart < decoded.length && decoded[outputStart] == 0) { 77 | ++outputStart; 78 | } 79 | // Return decoded data (including original number of leading zeros). 80 | return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length); 81 | } 82 | 83 | private static byte divmod(byte[] number, int firstDigit, int base, int divisor) { 84 | // this is just long division which accounts for the base of the input digits 85 | int remainder = 0; 86 | for (int i = firstDigit; i < number.length; i++) { 87 | int digit = (int) number[i] & 0xFF; 88 | int temp = remainder * base + digit; 89 | number[i] = (byte) (temp / divisor); 90 | remainder = temp % divisor; 91 | } 92 | return (byte) remainder; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/core/ECKey.java: -------------------------------------------------------------------------------- 1 | package core; 2 | 3 | import core.cryptohash.HashUtil; 4 | import org.spongycastle.asn1.sec.SECNamedCurves; 5 | import org.spongycastle.asn1.x9.X9ECParameters; 6 | import org.spongycastle.crypto.AsymmetricCipherKeyPair; 7 | import org.spongycastle.crypto.generators.ECKeyPairGenerator; 8 | import org.spongycastle.crypto.params.*; 9 | import org.spongycastle.math.ec.ECPoint; 10 | import javax.annotation.Nullable; 11 | import java.io.Serializable; 12 | import java.math.BigInteger; 13 | import java.security.SecureRandom; 14 | import java.util.Arrays; 15 | 16 | 17 | public class ECKey implements Serializable { 18 | 19 | /** 20 | * The parameters of the secp256k1 curve that Ethereum uses. 21 | */ 22 | public static final ECDomainParameters CURVE; 23 | 24 | /** 25 | * Equal to CURVE.getN().shiftRight(1), used for canonicalising the S value of a signature. If you aren't 26 | * sure what this is about, you can ignore it. 27 | */ 28 | public static final BigInteger HALF_CURVE_ORDER; 29 | 30 | private static final SecureRandom secureRandom; 31 | private static final long serialVersionUID = -728224901792295832L; 32 | 33 | static { 34 | // All clients must agree on the curve to use by agreement. Ethereum uses secp256k1. 35 | X9ECParameters params = SECNamedCurves.getByName("secp256k1"); 36 | CURVE = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); 37 | HALF_CURVE_ORDER = params.getN().shiftRight(1); 38 | secureRandom = new SecureRandom(); 39 | } 40 | 41 | // The two parts of the key. If "priv" is set, "pub" can always be calculated. If "pub" is set but not "priv", we 42 | // can only verify signatures not make them. 43 | // TODO: Redesign this class to use consistent internals and more efficient serialization. 44 | private BigInteger priv; 45 | protected final ECPoint pub; 46 | 47 | // Transient because it's calculated on demand. 48 | private transient byte[] pubKeyHash; 49 | private transient byte[] nodeId; 50 | 51 | /** 52 | * Generates an entirely new keypair. Point compression is used so the resulting public key will be 33 bytes 53 | * (32 for the co-ordinate and 1 byte to represent the y bit). 54 | */ 55 | public ECKey() { 56 | this(secureRandom); 57 | } 58 | 59 | /** 60 | * Generates an entirely new keypair with the given {@link SecureRandom} object. Point compression is used so the 61 | * resulting public key will be 33 bytes (32 for the co-ordinate and 1 byte to represent the y bit). 62 | * 63 | * @param secureRandom - 64 | */ 65 | public ECKey(SecureRandom secureRandom) { 66 | ECKeyPairGenerator generator = new ECKeyPairGenerator(); 67 | ECKeyGenerationParameters keygenParams = new ECKeyGenerationParameters(CURVE, secureRandom); 68 | generator.init(keygenParams); 69 | AsymmetricCipherKeyPair keypair = generator.generateKeyPair(); 70 | ECPrivateKeyParameters privParams = (ECPrivateKeyParameters) keypair.getPrivate(); 71 | ECPublicKeyParameters pubParams = (ECPublicKeyParameters) keypair.getPublic(); 72 | priv = privParams.getD(); 73 | pub = CURVE.getCurve().decodePoint(pubParams.getQ().getEncoded(true)); 74 | } 75 | 76 | public ECKey(@Nullable BigInteger priv, ECPoint pub) { 77 | this.priv = priv; 78 | if (pub == null) { 79 | throw new IllegalArgumentException("Public key may not be null"); 80 | } 81 | this.pub = pub; 82 | } 83 | 84 | /** 85 | * Utility for compressing an elliptic curve point. Returns the same point if it's already compressed. 86 | * See the ECKey class docs for a discussion of point compression. 87 | * 88 | * @param uncompressed - 89 | * 90 | * @return - 91 | */ 92 | public static ECPoint compressPoint(ECPoint uncompressed) { 93 | return CURVE.getCurve().decodePoint(uncompressed.getEncoded(true)); 94 | } 95 | 96 | /** 97 | * Utility for decompressing an elliptic curve point. Returns the same point if it's already compressed. 98 | * See the ECKey class docs for a discussion of point compression. 99 | * 100 | * @param compressed - 101 | * 102 | * @return - 103 | */ 104 | public static ECPoint decompressPoint(ECPoint compressed) { 105 | return CURVE.getCurve().decodePoint(compressed.getEncoded(false)); 106 | } 107 | 108 | /** 109 | * Creates an ECKey given the private key only. The public key is calculated from it (this is slow). Note that 110 | * the resulting public key is compressed. 111 | * 112 | * @param privKey - 113 | * 114 | * 115 | * @return - 116 | */ 117 | public static ECKey fromPrivate(BigInteger privKey) { 118 | return new ECKey(privKey, compressPoint(CURVE.getG().multiply(privKey))); 119 | } 120 | 121 | /** 122 | * Creates an ECKey given the private key only. The public key is calculated from it (this is slow). The resulting 123 | * public key is compressed. 124 | * 125 | * @param privKeyBytes - 126 | * 127 | * @return - 128 | */ 129 | public static ECKey fromPrivate(byte[] privKeyBytes) { 130 | return fromPrivate(new BigInteger(1, privKeyBytes)); 131 | } 132 | 133 | /** 134 | * Gets the hash160 form of the public key (as seen in addresses). 135 | * 136 | * @return - 137 | */ 138 | public byte[] getAddress() { 139 | if (pubKeyHash == null) { 140 | byte[] pubBytes = this.pub.getEncoded(false); 141 | pubKeyHash = HashUtil.sha3omit12(Arrays.copyOfRange(pubBytes, 1, pubBytes.length)); 142 | } 143 | return pubKeyHash; 144 | } 145 | 146 | /** 147 | * Gets the raw public key value. This appears in transaction scriptSigs. Note that this is not the same 148 | * as the pubKeyHash/address. 149 | * 150 | * @return - 151 | */ 152 | public byte[] getPubKey() { 153 | return pub.getEncoded(false); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/core/Sha256Hash.java: -------------------------------------------------------------------------------- 1 | package core; 2 | 3 | import java.io.Serializable; 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | import static com.google.common.base.Preconditions.checkArgument; 8 | 9 | public class Sha256Hash implements Serializable, Comparable { 10 | public static final int LENGTH = 32; // bytes 11 | 12 | private final byte[] bytes; 13 | 14 | private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); 15 | 16 | public static String bytesToHex(byte[] bytes) { 17 | char[] hexChars = new char[bytes.length * 2]; 18 | for ( int j = 0; j < bytes.length; j++ ) { 19 | int v = bytes[j] & 0xFF; 20 | hexChars[j * 2] = hexArray[v >>> 4]; 21 | hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 22 | } 23 | return new String(hexChars); 24 | } 25 | 26 | public static byte[] hexStringToByteArray(String s) { 27 | int len = s.length(); 28 | byte[] data = new byte[len / 2]; 29 | for (int i = 0; i < len; i += 2) { 30 | data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 31 | + Character.digit(s.charAt(i+1), 16)); 32 | } 33 | return data; 34 | } 35 | 36 | @Deprecated 37 | public Sha256Hash(byte[] rawHashBytes) { 38 | checkArgument(rawHashBytes.length == LENGTH); 39 | this.bytes = rawHashBytes; 40 | } 41 | 42 | @Deprecated 43 | public Sha256Hash(String hexString) { 44 | checkArgument(hexString.length() == LENGTH * 2); 45 | this.bytes = Utils.HEX.decode(hexString); 46 | } 47 | 48 | public static MessageDigest newDigest() { 49 | try { 50 | return MessageDigest.getInstance("SHA-256"); 51 | } catch (NoSuchAlgorithmException e) { 52 | throw new RuntimeException(e); // Can't happen. 53 | } 54 | } 55 | 56 | public static byte[] hashTwice(byte[] input) { 57 | return hashTwice(input, 0, input.length); 58 | } 59 | 60 | public static byte[] hashTwice(byte[] input, int offset, int length) { 61 | MessageDigest digest = newDigest(); 62 | digest.update(input, offset, length); 63 | return digest.digest(digest.digest()); 64 | } 65 | 66 | public static byte[] hashTwice(byte[] input1, int offset1, int length1, 67 | byte[] input2, int offset2, int length2) { 68 | MessageDigest digest = newDigest(); 69 | digest.update(input1, offset1, length1); 70 | digest.update(input2, offset2, length2); 71 | return digest.digest(digest.digest()); 72 | } 73 | 74 | @Override 75 | public int compareTo(final Sha256Hash other) { 76 | for (int i = LENGTH - 1; i >= 0; i--) { 77 | final int thisByte = this.bytes[i] & 0xff; 78 | final int otherByte = other.bytes[i] & 0xff; 79 | if (thisByte > otherByte) 80 | return 1; 81 | if (thisByte < otherByte) 82 | return -1; 83 | } 84 | return 0; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/core/Utils.java: -------------------------------------------------------------------------------- 1 | package core; 2 | 3 | import com.google.common.io.BaseEncoding; 4 | 5 | public class Utils { 6 | 7 | public static final BaseEncoding HEX = BaseEncoding.base16().lowerCase(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/core/cryptohash/Digest.java: -------------------------------------------------------------------------------- 1 | package core.cryptohash; 2 | 3 | public interface Digest { 4 | 5 | public void update(byte[] inbuf); 6 | 7 | public int getDigestLength(); 8 | 9 | public int getBlockLength(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/core/cryptohash/DigestEngine.java: -------------------------------------------------------------------------------- 1 | package core.cryptohash; 2 | 3 | public abstract class DigestEngine implements Digest { 4 | 5 | protected abstract void engineReset(); 6 | 7 | protected abstract void doInit(); 8 | 9 | protected abstract void processBlock(byte[] data); 10 | 11 | protected abstract void doPadding(byte[] buf, int off); 12 | 13 | private int digestLen; 14 | private int blockLen; 15 | private int inputLen; 16 | private byte[] inputBuf; 17 | byte[] outputBuf; 18 | private long blockCount; 19 | 20 | public DigestEngine() 21 | { 22 | doInit(); 23 | digestLen = getDigestLength(); 24 | blockLen = getInternalBlockLength(); 25 | inputBuf = new byte[blockLen]; 26 | outputBuf = new byte[digestLen]; 27 | inputLen = 0; 28 | blockCount = 0; 29 | } 30 | 31 | private void adjustDigestLen() 32 | { 33 | if (digestLen == 0) { 34 | digestLen = getDigestLength(); 35 | outputBuf = new byte[digestLen]; 36 | } 37 | } 38 | 39 | public byte[] digest() 40 | { 41 | adjustDigestLen(); 42 | byte[] result = new byte[digestLen]; 43 | digest(result, 0, digestLen); 44 | return result; 45 | } 46 | 47 | public int digest(byte[] buf, int offset, int len) 48 | { 49 | adjustDigestLen(); 50 | if (len >= digestLen) { 51 | doPadding(buf, offset); 52 | reset(); 53 | return digestLen; 54 | } else { 55 | doPadding(outputBuf, 0); 56 | System.arraycopy(outputBuf, 0, buf, offset, len); 57 | reset(); 58 | return len; 59 | } 60 | } 61 | 62 | public void reset() 63 | { 64 | engineReset(); 65 | inputLen = 0; 66 | blockCount = 0; 67 | } 68 | 69 | public void update(byte[] input) 70 | { 71 | update(input, 0, input.length); 72 | } 73 | 74 | public void update(byte[] input, int offset, int len) 75 | { 76 | while (len > 0) { 77 | int copyLen = blockLen - inputLen; 78 | if (copyLen > len) { 79 | copyLen = len; 80 | } 81 | System.arraycopy(input, offset, inputBuf, inputLen, 82 | copyLen); 83 | offset += copyLen; 84 | inputLen += copyLen; 85 | len -= copyLen; 86 | if (inputLen == blockLen) { 87 | processBlock(inputBuf); 88 | blockCount ++; 89 | inputLen = 0; 90 | } 91 | } 92 | } 93 | 94 | protected int getInternalBlockLength() 95 | { 96 | return getBlockLength(); 97 | } 98 | 99 | protected final int flush() 100 | { 101 | return inputLen; 102 | } 103 | 104 | protected final byte[] getBlockBuffer() 105 | { 106 | return inputBuf; 107 | } 108 | 109 | protected Digest copyState(DigestEngine dest) 110 | { 111 | dest.inputLen = inputLen; 112 | dest.blockCount = blockCount; 113 | System.arraycopy(inputBuf, 0, dest.inputBuf, 0, 114 | inputBuf.length); 115 | adjustDigestLen(); 116 | dest.adjustDigestLen(); 117 | System.arraycopy(outputBuf, 0, dest.outputBuf, 0, 118 | outputBuf.length); 119 | return dest; 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /src/main/java/core/cryptohash/HashUtil.java: -------------------------------------------------------------------------------- 1 | package core.cryptohash; 2 | 3 | import core.cryptohash.Keccak256; 4 | 5 | import static java.util.Arrays.copyOfRange; 6 | 7 | public class HashUtil { 8 | /** 9 | * Calculates RIGTMOST160(SHA3(input)). This is used in address calculations. 10 | * * 11 | * @param input - data 12 | * @return - 20 right bytes of the hash sha3 of the data 13 | */ 14 | public static byte[] sha3omit12(byte[] input) { 15 | byte[] hash = keccak256(input); 16 | return copyOfRange(hash, 12, hash.length); 17 | } 18 | 19 | public static byte[] keccak256(byte[] input) { 20 | Keccak256 digest = new Keccak256(); 21 | digest.update(input); 22 | return digest.digest(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/core/cryptohash/Keccak256.java: -------------------------------------------------------------------------------- 1 | package core.cryptohash; 2 | 3 | public class Keccak256 extends KeccakCore { 4 | 5 | /** 6 | * Create the engine. 7 | */ 8 | public Keccak256() 9 | { 10 | } 11 | 12 | public Digest copy() 13 | { 14 | return copyState(new Keccak256()); 15 | } 16 | 17 | public int getDigestLength() 18 | { 19 | return 32; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/core/cryptohash/KeccakCore.java: -------------------------------------------------------------------------------- 1 | package core.cryptohash; 2 | 3 | abstract class KeccakCore extends DigestEngine{ 4 | 5 | KeccakCore() 6 | { 7 | } 8 | 9 | private long[] a; 10 | private byte[] tmpOut; 11 | 12 | private static final long[] RC = { 13 | 0x0000000000000001L, 0x0000000000008082L, 14 | 0x800000000000808AL, 0x8000000080008000L, 15 | 0x000000000000808BL, 0x0000000080000001L, 16 | 0x8000000080008081L, 0x8000000000008009L, 17 | 0x000000000000008AL, 0x0000000000000088L, 18 | 0x0000000080008009L, 0x000000008000000AL, 19 | 0x000000008000808BL, 0x800000000000008BL, 20 | 0x8000000000008089L, 0x8000000000008003L, 21 | 0x8000000000008002L, 0x8000000000000080L, 22 | 0x000000000000800AL, 0x800000008000000AL, 23 | 0x8000000080008081L, 0x8000000000008080L, 24 | 0x0000000080000001L, 0x8000000080008008L 25 | }; 26 | 27 | private static final void encodeLELong(long val, byte[] buf, int off) 28 | { 29 | buf[off + 0] = (byte)val; 30 | buf[off + 1] = (byte)(val >>> 8); 31 | buf[off + 2] = (byte)(val >>> 16); 32 | buf[off + 3] = (byte)(val >>> 24); 33 | buf[off + 4] = (byte)(val >>> 32); 34 | buf[off + 5] = (byte)(val >>> 40); 35 | buf[off + 6] = (byte)(val >>> 48); 36 | buf[off + 7] = (byte)(val >>> 56); 37 | } 38 | 39 | private static final long decodeLELong(byte[] buf, int off) 40 | { 41 | return (buf[off + 0] & 0xFFL) 42 | | ((buf[off + 1] & 0xFFL) << 8) 43 | | ((buf[off + 2] & 0xFFL) << 16) 44 | | ((buf[off + 3] & 0xFFL) << 24) 45 | | ((buf[off + 4] & 0xFFL) << 32) 46 | | ((buf[off + 5] & 0xFFL) << 40) 47 | | ((buf[off + 6] & 0xFFL) << 48) 48 | | ((buf[off + 7] & 0xFFL) << 56); 49 | } 50 | 51 | protected Digest copyState(KeccakCore dst) 52 | { 53 | System.arraycopy(a, 0, dst.a, 0, 25); 54 | return super.copyState(dst); 55 | } 56 | 57 | public int getBlockLength() 58 | { 59 | return 200 - 2 * getDigestLength(); 60 | } 61 | 62 | protected void doPadding(byte[] out, int off) 63 | { 64 | int ptr = flush(); 65 | byte[] buf = getBlockBuffer(); 66 | if ((ptr + 1) == buf.length) { 67 | buf[ptr] = (byte)0x81; 68 | } else { 69 | buf[ptr] = (byte)0x01; 70 | for (int i = ptr + 1; i < (buf.length - 1); i ++) { 71 | buf[i] = 0; 72 | } 73 | buf[buf.length - 1] = (byte)0x80; 74 | } 75 | processBlock(buf); 76 | a[ 1] = ~a[ 1]; 77 | a[ 2] = ~a[ 2]; 78 | a[ 8] = ~a[ 8]; 79 | a[12] = ~a[12]; 80 | a[17] = ~a[17]; 81 | a[20] = ~a[20]; 82 | int dlen = getDigestLength(); 83 | for (int i = 0; i < dlen; i += 8) { 84 | encodeLELong(a[i >>> 3], tmpOut, i); 85 | } 86 | System.arraycopy(tmpOut, 0, out, off, dlen); 87 | } 88 | 89 | protected void doInit() 90 | { 91 | a = new long[25]; 92 | tmpOut = new byte[(getDigestLength() + 7) & ~7]; 93 | doReset(); 94 | } 95 | 96 | private final void doReset() 97 | { 98 | for (int i = 0; i < 25; i ++) { 99 | a[i] = 0; 100 | } 101 | a[ 1] = 0xFFFFFFFFFFFFFFFFL; 102 | a[ 2] = 0xFFFFFFFFFFFFFFFFL; 103 | a[ 8] = 0xFFFFFFFFFFFFFFFFL; 104 | a[12] = 0xFFFFFFFFFFFFFFFFL; 105 | a[17] = 0xFFFFFFFFFFFFFFFFL; 106 | a[20] = 0xFFFFFFFFFFFFFFFFL; 107 | } 108 | 109 | protected void engineReset() 110 | { 111 | doReset(); 112 | } 113 | 114 | protected void processBlock(byte[] data) 115 | { 116 | /* Input block */ 117 | for (int i = 0; i < data.length; i += 8) { 118 | a[i >>> 3] ^= decodeLELong(data, i); 119 | } 120 | 121 | long t0; 122 | long t1; 123 | long t2; 124 | long t3; 125 | long t4; 126 | long tt0; 127 | long tt1; 128 | long tt2; 129 | long tt3; 130 | long tt4; 131 | long t; 132 | long kt; 133 | long c0; 134 | long c1; 135 | long c2; 136 | long c3; 137 | long c4; 138 | long bnn; 139 | 140 | /* 141 | * Unrolling four rounds kills performance big time 142 | * on Intel x86 Core2, in both 32-bit and 64-bit modes 143 | * (less than 1 MB/s instead of 55 MB/s on x86-64). 144 | * Unrolling two rounds appears to be fine. 145 | */ 146 | for (int j = 0; j < 24; j += 2) { 147 | 148 | tt0 = a[ 1] ^ a[ 6]; 149 | tt1 = a[11] ^ a[16]; 150 | tt0 ^= a[21] ^ tt1; 151 | tt0 = (tt0 << 1) | (tt0 >>> 63); 152 | tt2 = a[ 4] ^ a[ 9]; 153 | tt3 = a[14] ^ a[19]; 154 | tt0 ^= a[24]; 155 | tt2 ^= tt3; 156 | t0 = tt0 ^ tt2; 157 | 158 | tt0 = a[ 2] ^ a[ 7]; 159 | tt1 = a[12] ^ a[17]; 160 | tt0 ^= a[22] ^ tt1; 161 | tt0 = (tt0 << 1) | (tt0 >>> 63); 162 | tt2 = a[ 0] ^ a[ 5]; 163 | tt3 = a[10] ^ a[15]; 164 | tt0 ^= a[20]; 165 | tt2 ^= tt3; 166 | t1 = tt0 ^ tt2; 167 | 168 | tt0 = a[ 3] ^ a[ 8]; 169 | tt1 = a[13] ^ a[18]; 170 | tt0 ^= a[23] ^ tt1; 171 | tt0 = (tt0 << 1) | (tt0 >>> 63); 172 | tt2 = a[ 1] ^ a[ 6]; 173 | tt3 = a[11] ^ a[16]; 174 | tt0 ^= a[21]; 175 | tt2 ^= tt3; 176 | t2 = tt0 ^ tt2; 177 | 178 | tt0 = a[ 4] ^ a[ 9]; 179 | tt1 = a[14] ^ a[19]; 180 | tt0 ^= a[24] ^ tt1; 181 | tt0 = (tt0 << 1) | (tt0 >>> 63); 182 | tt2 = a[ 2] ^ a[ 7]; 183 | tt3 = a[12] ^ a[17]; 184 | tt0 ^= a[22]; 185 | tt2 ^= tt3; 186 | t3 = tt0 ^ tt2; 187 | 188 | tt0 = a[ 0] ^ a[ 5]; 189 | tt1 = a[10] ^ a[15]; 190 | tt0 ^= a[20] ^ tt1; 191 | tt0 = (tt0 << 1) | (tt0 >>> 63); 192 | tt2 = a[ 3] ^ a[ 8]; 193 | tt3 = a[13] ^ a[18]; 194 | tt0 ^= a[23]; 195 | tt2 ^= tt3; 196 | t4 = tt0 ^ tt2; 197 | 198 | a[ 0] = a[ 0] ^ t0; 199 | a[ 5] = a[ 5] ^ t0; 200 | a[10] = a[10] ^ t0; 201 | a[15] = a[15] ^ t0; 202 | a[20] = a[20] ^ t0; 203 | a[ 1] = a[ 1] ^ t1; 204 | a[ 6] = a[ 6] ^ t1; 205 | a[11] = a[11] ^ t1; 206 | a[16] = a[16] ^ t1; 207 | a[21] = a[21] ^ t1; 208 | a[ 2] = a[ 2] ^ t2; 209 | a[ 7] = a[ 7] ^ t2; 210 | a[12] = a[12] ^ t2; 211 | a[17] = a[17] ^ t2; 212 | a[22] = a[22] ^ t2; 213 | a[ 3] = a[ 3] ^ t3; 214 | a[ 8] = a[ 8] ^ t3; 215 | a[13] = a[13] ^ t3; 216 | a[18] = a[18] ^ t3; 217 | a[23] = a[23] ^ t3; 218 | a[ 4] = a[ 4] ^ t4; 219 | a[ 9] = a[ 9] ^ t4; 220 | a[14] = a[14] ^ t4; 221 | a[19] = a[19] ^ t4; 222 | a[24] = a[24] ^ t4; 223 | a[ 5] = (a[ 5] << 36) | (a[ 5] >>> (64 - 36)); 224 | a[10] = (a[10] << 3) | (a[10] >>> (64 - 3)); 225 | a[15] = (a[15] << 41) | (a[15] >>> (64 - 41)); 226 | a[20] = (a[20] << 18) | (a[20] >>> (64 - 18)); 227 | a[ 1] = (a[ 1] << 1) | (a[ 1] >>> (64 - 1)); 228 | a[ 6] = (a[ 6] << 44) | (a[ 6] >>> (64 - 44)); 229 | a[11] = (a[11] << 10) | (a[11] >>> (64 - 10)); 230 | a[16] = (a[16] << 45) | (a[16] >>> (64 - 45)); 231 | a[21] = (a[21] << 2) | (a[21] >>> (64 - 2)); 232 | a[ 2] = (a[ 2] << 62) | (a[ 2] >>> (64 - 62)); 233 | a[ 7] = (a[ 7] << 6) | (a[ 7] >>> (64 - 6)); 234 | a[12] = (a[12] << 43) | (a[12] >>> (64 - 43)); 235 | a[17] = (a[17] << 15) | (a[17] >>> (64 - 15)); 236 | a[22] = (a[22] << 61) | (a[22] >>> (64 - 61)); 237 | a[ 3] = (a[ 3] << 28) | (a[ 3] >>> (64 - 28)); 238 | a[ 8] = (a[ 8] << 55) | (a[ 8] >>> (64 - 55)); 239 | a[13] = (a[13] << 25) | (a[13] >>> (64 - 25)); 240 | a[18] = (a[18] << 21) | (a[18] >>> (64 - 21)); 241 | a[23] = (a[23] << 56) | (a[23] >>> (64 - 56)); 242 | a[ 4] = (a[ 4] << 27) | (a[ 4] >>> (64 - 27)); 243 | a[ 9] = (a[ 9] << 20) | (a[ 9] >>> (64 - 20)); 244 | a[14] = (a[14] << 39) | (a[14] >>> (64 - 39)); 245 | a[19] = (a[19] << 8) | (a[19] >>> (64 - 8)); 246 | a[24] = (a[24] << 14) | (a[24] >>> (64 - 14)); 247 | bnn = ~a[12]; 248 | kt = a[ 6] | a[12]; 249 | c0 = a[ 0] ^ kt; 250 | kt = bnn | a[18]; 251 | c1 = a[ 6] ^ kt; 252 | kt = a[18] & a[24]; 253 | c2 = a[12] ^ kt; 254 | kt = a[24] | a[ 0]; 255 | c3 = a[18] ^ kt; 256 | kt = a[ 0] & a[ 6]; 257 | c4 = a[24] ^ kt; 258 | a[ 0] = c0; 259 | a[ 6] = c1; 260 | a[12] = c2; 261 | a[18] = c3; 262 | a[24] = c4; 263 | bnn = ~a[22]; 264 | kt = a[ 9] | a[10]; 265 | c0 = a[ 3] ^ kt; 266 | kt = a[10] & a[16]; 267 | c1 = a[ 9] ^ kt; 268 | kt = a[16] | bnn; 269 | c2 = a[10] ^ kt; 270 | kt = a[22] | a[ 3]; 271 | c3 = a[16] ^ kt; 272 | kt = a[ 3] & a[ 9]; 273 | c4 = a[22] ^ kt; 274 | a[ 3] = c0; 275 | a[ 9] = c1; 276 | a[10] = c2; 277 | a[16] = c3; 278 | a[22] = c4; 279 | bnn = ~a[19]; 280 | kt = a[ 7] | a[13]; 281 | c0 = a[ 1] ^ kt; 282 | kt = a[13] & a[19]; 283 | c1 = a[ 7] ^ kt; 284 | kt = bnn & a[20]; 285 | c2 = a[13] ^ kt; 286 | kt = a[20] | a[ 1]; 287 | c3 = bnn ^ kt; 288 | kt = a[ 1] & a[ 7]; 289 | c4 = a[20] ^ kt; 290 | a[ 1] = c0; 291 | a[ 7] = c1; 292 | a[13] = c2; 293 | a[19] = c3; 294 | a[20] = c4; 295 | bnn = ~a[17]; 296 | kt = a[ 5] & a[11]; 297 | c0 = a[ 4] ^ kt; 298 | kt = a[11] | a[17]; 299 | c1 = a[ 5] ^ kt; 300 | kt = bnn | a[23]; 301 | c2 = a[11] ^ kt; 302 | kt = a[23] & a[ 4]; 303 | c3 = bnn ^ kt; 304 | kt = a[ 4] | a[ 5]; 305 | c4 = a[23] ^ kt; 306 | a[ 4] = c0; 307 | a[ 5] = c1; 308 | a[11] = c2; 309 | a[17] = c3; 310 | a[23] = c4; 311 | bnn = ~a[ 8]; 312 | kt = bnn & a[14]; 313 | c0 = a[ 2] ^ kt; 314 | kt = a[14] | a[15]; 315 | c1 = bnn ^ kt; 316 | kt = a[15] & a[21]; 317 | c2 = a[14] ^ kt; 318 | kt = a[21] | a[ 2]; 319 | c3 = a[15] ^ kt; 320 | kt = a[ 2] & a[ 8]; 321 | c4 = a[21] ^ kt; 322 | a[ 2] = c0; 323 | a[ 8] = c1; 324 | a[14] = c2; 325 | a[15] = c3; 326 | a[21] = c4; 327 | a[ 0] = a[ 0] ^ RC[j + 0]; 328 | 329 | tt0 = a[ 6] ^ a[ 9]; 330 | tt1 = a[ 7] ^ a[ 5]; 331 | tt0 ^= a[ 8] ^ tt1; 332 | tt0 = (tt0 << 1) | (tt0 >>> 63); 333 | tt2 = a[24] ^ a[22]; 334 | tt3 = a[20] ^ a[23]; 335 | tt0 ^= a[21]; 336 | tt2 ^= tt3; 337 | t0 = tt0 ^ tt2; 338 | 339 | tt0 = a[12] ^ a[10]; 340 | tt1 = a[13] ^ a[11]; 341 | tt0 ^= a[14] ^ tt1; 342 | tt0 = (tt0 << 1) | (tt0 >>> 63); 343 | tt2 = a[ 0] ^ a[ 3]; 344 | tt3 = a[ 1] ^ a[ 4]; 345 | tt0 ^= a[ 2]; 346 | tt2 ^= tt3; 347 | t1 = tt0 ^ tt2; 348 | 349 | tt0 = a[18] ^ a[16]; 350 | tt1 = a[19] ^ a[17]; 351 | tt0 ^= a[15] ^ tt1; 352 | tt0 = (tt0 << 1) | (tt0 >>> 63); 353 | tt2 = a[ 6] ^ a[ 9]; 354 | tt3 = a[ 7] ^ a[ 5]; 355 | tt0 ^= a[ 8]; 356 | tt2 ^= tt3; 357 | t2 = tt0 ^ tt2; 358 | 359 | tt0 = a[24] ^ a[22]; 360 | tt1 = a[20] ^ a[23]; 361 | tt0 ^= a[21] ^ tt1; 362 | tt0 = (tt0 << 1) | (tt0 >>> 63); 363 | tt2 = a[12] ^ a[10]; 364 | tt3 = a[13] ^ a[11]; 365 | tt0 ^= a[14]; 366 | tt2 ^= tt3; 367 | t3 = tt0 ^ tt2; 368 | 369 | tt0 = a[ 0] ^ a[ 3]; 370 | tt1 = a[ 1] ^ a[ 4]; 371 | tt0 ^= a[ 2] ^ tt1; 372 | tt0 = (tt0 << 1) | (tt0 >>> 63); 373 | tt2 = a[18] ^ a[16]; 374 | tt3 = a[19] ^ a[17]; 375 | tt0 ^= a[15]; 376 | tt2 ^= tt3; 377 | t4 = tt0 ^ tt2; 378 | 379 | a[ 0] = a[ 0] ^ t0; 380 | a[ 3] = a[ 3] ^ t0; 381 | a[ 1] = a[ 1] ^ t0; 382 | a[ 4] = a[ 4] ^ t0; 383 | a[ 2] = a[ 2] ^ t0; 384 | a[ 6] = a[ 6] ^ t1; 385 | a[ 9] = a[ 9] ^ t1; 386 | a[ 7] = a[ 7] ^ t1; 387 | a[ 5] = a[ 5] ^ t1; 388 | a[ 8] = a[ 8] ^ t1; 389 | a[12] = a[12] ^ t2; 390 | a[10] = a[10] ^ t2; 391 | a[13] = a[13] ^ t2; 392 | a[11] = a[11] ^ t2; 393 | a[14] = a[14] ^ t2; 394 | a[18] = a[18] ^ t3; 395 | a[16] = a[16] ^ t3; 396 | a[19] = a[19] ^ t3; 397 | a[17] = a[17] ^ t3; 398 | a[15] = a[15] ^ t3; 399 | a[24] = a[24] ^ t4; 400 | a[22] = a[22] ^ t4; 401 | a[20] = a[20] ^ t4; 402 | a[23] = a[23] ^ t4; 403 | a[21] = a[21] ^ t4; 404 | a[ 3] = (a[ 3] << 36) | (a[ 3] >>> (64 - 36)); 405 | a[ 1] = (a[ 1] << 3) | (a[ 1] >>> (64 - 3)); 406 | a[ 4] = (a[ 4] << 41) | (a[ 4] >>> (64 - 41)); 407 | a[ 2] = (a[ 2] << 18) | (a[ 2] >>> (64 - 18)); 408 | a[ 6] = (a[ 6] << 1) | (a[ 6] >>> (64 - 1)); 409 | a[ 9] = (a[ 9] << 44) | (a[ 9] >>> (64 - 44)); 410 | a[ 7] = (a[ 7] << 10) | (a[ 7] >>> (64 - 10)); 411 | a[ 5] = (a[ 5] << 45) | (a[ 5] >>> (64 - 45)); 412 | a[ 8] = (a[ 8] << 2) | (a[ 8] >>> (64 - 2)); 413 | a[12] = (a[12] << 62) | (a[12] >>> (64 - 62)); 414 | a[10] = (a[10] << 6) | (a[10] >>> (64 - 6)); 415 | a[13] = (a[13] << 43) | (a[13] >>> (64 - 43)); 416 | a[11] = (a[11] << 15) | (a[11] >>> (64 - 15)); 417 | a[14] = (a[14] << 61) | (a[14] >>> (64 - 61)); 418 | a[18] = (a[18] << 28) | (a[18] >>> (64 - 28)); 419 | a[16] = (a[16] << 55) | (a[16] >>> (64 - 55)); 420 | a[19] = (a[19] << 25) | (a[19] >>> (64 - 25)); 421 | a[17] = (a[17] << 21) | (a[17] >>> (64 - 21)); 422 | a[15] = (a[15] << 56) | (a[15] >>> (64 - 56)); 423 | a[24] = (a[24] << 27) | (a[24] >>> (64 - 27)); 424 | a[22] = (a[22] << 20) | (a[22] >>> (64 - 20)); 425 | a[20] = (a[20] << 39) | (a[20] >>> (64 - 39)); 426 | a[23] = (a[23] << 8) | (a[23] >>> (64 - 8)); 427 | a[21] = (a[21] << 14) | (a[21] >>> (64 - 14)); 428 | bnn = ~a[13]; 429 | kt = a[ 9] | a[13]; 430 | c0 = a[ 0] ^ kt; 431 | kt = bnn | a[17]; 432 | c1 = a[ 9] ^ kt; 433 | kt = a[17] & a[21]; 434 | c2 = a[13] ^ kt; 435 | kt = a[21] | a[ 0]; 436 | c3 = a[17] ^ kt; 437 | kt = a[ 0] & a[ 9]; 438 | c4 = a[21] ^ kt; 439 | a[ 0] = c0; 440 | a[ 9] = c1; 441 | a[13] = c2; 442 | a[17] = c3; 443 | a[21] = c4; 444 | bnn = ~a[14]; 445 | kt = a[22] | a[ 1]; 446 | c0 = a[18] ^ kt; 447 | kt = a[ 1] & a[ 5]; 448 | c1 = a[22] ^ kt; 449 | kt = a[ 5] | bnn; 450 | c2 = a[ 1] ^ kt; 451 | kt = a[14] | a[18]; 452 | c3 = a[ 5] ^ kt; 453 | kt = a[18] & a[22]; 454 | c4 = a[14] ^ kt; 455 | a[18] = c0; 456 | a[22] = c1; 457 | a[ 1] = c2; 458 | a[ 5] = c3; 459 | a[14] = c4; 460 | bnn = ~a[23]; 461 | kt = a[10] | a[19]; 462 | c0 = a[ 6] ^ kt; 463 | kt = a[19] & a[23]; 464 | c1 = a[10] ^ kt; 465 | kt = bnn & a[ 2]; 466 | c2 = a[19] ^ kt; 467 | kt = a[ 2] | a[ 6]; 468 | c3 = bnn ^ kt; 469 | kt = a[ 6] & a[10]; 470 | c4 = a[ 2] ^ kt; 471 | a[ 6] = c0; 472 | a[10] = c1; 473 | a[19] = c2; 474 | a[23] = c3; 475 | a[ 2] = c4; 476 | bnn = ~a[11]; 477 | kt = a[ 3] & a[ 7]; 478 | c0 = a[24] ^ kt; 479 | kt = a[ 7] | a[11]; 480 | c1 = a[ 3] ^ kt; 481 | kt = bnn | a[15]; 482 | c2 = a[ 7] ^ kt; 483 | kt = a[15] & a[24]; 484 | c3 = bnn ^ kt; 485 | kt = a[24] | a[ 3]; 486 | c4 = a[15] ^ kt; 487 | a[24] = c0; 488 | a[ 3] = c1; 489 | a[ 7] = c2; 490 | a[11] = c3; 491 | a[15] = c4; 492 | bnn = ~a[16]; 493 | kt = bnn & a[20]; 494 | c0 = a[12] ^ kt; 495 | kt = a[20] | a[ 4]; 496 | c1 = bnn ^ kt; 497 | kt = a[ 4] & a[ 8]; 498 | c2 = a[20] ^ kt; 499 | kt = a[ 8] | a[12]; 500 | c3 = a[ 4] ^ kt; 501 | kt = a[12] & a[16]; 502 | c4 = a[ 8] ^ kt; 503 | a[12] = c0; 504 | a[16] = c1; 505 | a[20] = c2; 506 | a[ 4] = c3; 507 | a[ 8] = c4; 508 | a[ 0] = a[ 0] ^ RC[j + 1]; 509 | t = a[ 5]; 510 | a[ 5] = a[18]; 511 | a[18] = a[11]; 512 | a[11] = a[10]; 513 | a[10] = a[ 6]; 514 | a[ 6] = a[22]; 515 | a[22] = a[20]; 516 | a[20] = a[12]; 517 | a[12] = a[19]; 518 | a[19] = a[15]; 519 | a[15] = a[24]; 520 | a[24] = a[ 8]; 521 | a[ 8] = t; 522 | t = a[ 1]; 523 | a[ 1] = a[ 9]; 524 | a[ 9] = a[14]; 525 | a[14] = a[ 2]; 526 | a[ 2] = a[13]; 527 | a[13] = a[23]; 528 | a[23] = a[ 4]; 529 | a[ 4] = a[21]; 530 | a[21] = a[16]; 531 | a[16] = a[ 3]; 532 | a[ 3] = a[17]; 533 | a[17] = a[ 7]; 534 | a[ 7] = t; 535 | } 536 | } 537 | } 538 | -------------------------------------------------------------------------------- /src/main/java/utils/UscConversionUtils.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | 4 | import core.Base58; 5 | import core.ECKey; 6 | import core.Sha256Hash; 7 | 8 | 9 | import java.util.Arrays; 10 | 11 | public class UscConversionUtils { 12 | 13 | private static byte[] keyUldToUscInBytes(String privKeyAsExportedByUlordDumpprivkey){ 14 | byte[] decodedKey = Base58.decode(privKeyAsExportedByUlordDumpprivkey); 15 | byte[] privKeyBytes = Arrays.copyOfRange(decodedKey,1,decodedKey.length - 5); 16 | return privKeyBytes; 17 | } 18 | 19 | public static String privKeyToUscFormat(String uldPrivateKey){ 20 | byte []privKeyBytes = keyUldToUscInBytes(uldPrivateKey); 21 | String privKeyInUscFormat = Sha256Hash.bytesToHex(privKeyBytes); 22 | return privKeyInUscFormat; 23 | } 24 | 25 | public static String getUscAddress(String uscPrivateKey){ 26 | ECKey ecKey = ECKey.fromPrivate(Sha256Hash.hexStringToByteArray(uscPrivateKey)); 27 | byte[] addressInUscFormat = ecKey.getAddress(); 28 | return Sha256Hash.bytesToHex(addressInUscFormat); 29 | } 30 | 31 | public static String getUscPubKey(String uscPrivateKey){ 32 | ECKey ecKey = ECKey.fromPrivate(Sha256Hash.hexStringToByteArray(uscPrivateKey)); 33 | byte []pubKey = ecKey.getPubKey(); 34 | return Sha256Hash.bytesToHex(pubKey); 35 | } 36 | 37 | public static String getUldPrivateKey(String uldNet, String uscPrivateKey){ 38 | byte[] uscPrivateKeyArray = Sha256Hash.hexStringToByteArray(uscPrivateKey); 39 | byte[] partialResult = new byte[uscPrivateKeyArray.length+2]; 40 | byte[] result = null; 41 | if(uldNet.equals("main")) { 42 | partialResult[0] = (byte)0x80; 43 | } else { 44 | partialResult[0] = (byte)0xEF; 45 | } 46 | 47 | for (int i = 1; i <= uscPrivateKeyArray.length; i++) { 48 | partialResult[i] = (uscPrivateKeyArray[i-1]); 49 | } 50 | partialResult[uscPrivateKeyArray.length+1] = (byte)0x01; 51 | 52 | result = new byte[partialResult.length+4]; 53 | 54 | byte[] check = Sha256Hash.hashTwice(partialResult); 55 | 56 | for (int i = 0; i < partialResult.length; i++) { 57 | result[i] = partialResult[i]; 58 | } 59 | 60 | for (int i = 0; i < 4; i++) { 61 | result[partialResult.length+i] = check[i]; 62 | } 63 | 64 | return Base58.encode(result); 65 | } 66 | } 67 | --------------------------------------------------------------------------------