├── gson-1.7.1.jar
├── README
├── src
└── com
│ ├── dvanderbleek
│ └── miner
│ │ ├── Work.java
│ │ ├── Result.java
│ │ ├── Miner.java
│ │ └── Converter.java
│ └── lambdaworks
│ └── crypto
│ ├── test
│ ├── CryptoTestUtil.java
│ ├── SCryptUtilTest.java
│ ├── SCryptTest.java
│ └── PBKDFTest.java
│ ├── PBKDF.java
│ ├── SCryptUtil.java
│ ├── SCrypt.java
│ └── Base64.java
├── .classpath
└── .project
/gson-1.7.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vanderbleek/JavaSCryptMiner/HEAD/gson-1.7.1.jar
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | This is a miner for litecoins, written in Java. It uses the sCrypt implementation found at https://github.com/wg/scrypt
2 | Converter class from http://www.daniweb.com/software-development/java/code/216874
--------------------------------------------------------------------------------
/src/com/dvanderbleek/miner/Work.java:
--------------------------------------------------------------------------------
1 | package com.dvanderbleek.miner;
2 | //Class to make parsing JSON with GSON easier.
3 |
4 |
5 | public class Work {
6 | Result result;
7 |
8 | public Work(Result result){
9 | this.result = result;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 | $s0$PARAMS$SALT$KEY.
19 | *
20 | *
s0 identifies version 0 of the scrypt format, using a 128-bit salt and 256-bit derived key.
27 | *
28 | * @author Will Glozer
29 | */
30 | public class SCryptUtil {
31 | /**
32 | * Hash the supplied plaintext password and generate output in the format described
33 | * in {@link SCryptUtil}.
34 | *
35 | * @param passwd Password.
36 | * @param N CPU cost parameter.
37 | * @param r Memory cost parameter.
38 | * @param p Parallelization parameter.
39 | *
40 | * @return The hashed password.
41 | */
42 | public static String scrypt(String passwd, int N, int r, int p) {
43 | try {
44 | byte[] salt = new byte[16];
45 | SecureRandom.getInstance("SHA1PRNG").nextBytes(salt);
46 |
47 | byte[] derived = SCrypt.scrypt(passwd.getBytes("UTF-8"), salt, N, r, p, 32);
48 |
49 | String params = Integer.toString(log2(N) << 16 | r << 8 | p, 16);
50 |
51 | StringBuilder sb = new StringBuilder((salt.length + derived.length) * 2);
52 | sb.append("$s0$").append(params).append('$');
53 | sb.append(encodeToChar(salt, false)).append('$');
54 | sb.append(encodeToChar(derived, false));
55 |
56 | return sb.toString();
57 | } catch (UnsupportedEncodingException e) {
58 | throw new IllegalStateException("JVM doesn't support UTF-8?");
59 | } catch (GeneralSecurityException e) {
60 | throw new IllegalStateException("JVM doesn't support SHA1PRNG or HMAC_SHA256?");
61 | }
62 | }
63 |
64 | /**
65 | * Compare the supplied plaintext password to a hashed password.
66 | *
67 | * @param passwd Plaintext password.
68 | * @param hashed scrypt hashed password.
69 | *
70 | * @return true if passwd matches hashed value.
71 | */
72 | public static boolean check(String passwd, String hashed) {
73 | try {
74 | String[] parts = hashed.split("\\$");
75 |
76 | if (parts.length != 5 || !parts[1].equals("s0")) {
77 | throw new IllegalArgumentException("Invalid hashed value");
78 | }
79 |
80 | int params = Integer.parseInt(parts[2], 16);
81 | byte[] salt = decodeFast(parts[3].toCharArray());
82 | byte[] derived0 = decodeFast(parts[4].toCharArray());
83 |
84 | int N = (int) Math.pow(2, params >> 16 & 0xff);
85 | int r = params >> 8 & 0x0f;
86 | int p = params & 0x0f;
87 |
88 | byte[] derived1 = SCrypt.scrypt(passwd.getBytes("UTF-8"), salt, N, r, p, 32);
89 |
90 | if (derived0.length != derived1.length) return false;
91 |
92 | int result = 0;
93 | for (int i = 0; i < derived0.length; i++) {
94 | result |= derived0[i] ^ derived1[i];
95 | }
96 | return result == 0;
97 | } catch (UnsupportedEncodingException e) {
98 | throw new IllegalStateException("JVM doesn't support UTF-8?");
99 | } catch (GeneralSecurityException e) {
100 | throw new IllegalStateException("JVM doesn't support SHA1PRNG or HMAC_SHA256?");
101 | }
102 | }
103 |
104 | private static int log2(int n) {
105 | int log = 0;
106 | if ((n & 0xffff0000 ) != 0) { n >>>= 16; log = 16; }
107 | if (n >= 256) { n >>>= 8; log += 8; }
108 | if (n >= 16 ) { n >>>= 4; log += 4; }
109 | if (n >= 4 ) { n >>>= 2; log += 2; }
110 | return log + (n >>> 1);
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/com/lambdaworks/crypto/test/PBKDFTest.java:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2011 - Will Glozer. All rights reserved.
2 |
3 | package com.lambdaworks.crypto.test;
4 |
5 | import com.lambdaworks.crypto.PBKDF;
6 | import org.junit.Test;
7 |
8 | import java.math.BigInteger;
9 |
10 | import static org.junit.Assert.*;
11 | import static com.lambdaworks.crypto.test.CryptoTestUtil.*;
12 |
13 | public class PBKDFTest {
14 | @Test
15 | public void pbkdf2_hmac_sha1_rfc6070() throws Exception {
16 | String alg = "HmacSHA1";
17 | byte[] P, S;
18 | int c, dkLen;
19 | String DK;
20 |
21 | P = "password".getBytes("UTF-8");
22 | S = "salt".getBytes("UTF-8");
23 | c = 1;
24 | dkLen = 20;
25 | DK = "0c60c80f961f0e71f3a9b524af6012062fe037a6";
26 |
27 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
28 |
29 | P = "password".getBytes("UTF-8");
30 | S = "salt".getBytes("UTF-8");
31 | c = 2;
32 | dkLen = 20;
33 | DK = "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957";
34 |
35 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
36 |
37 | P = "password".getBytes("UTF-8");
38 | S = "salt".getBytes("UTF-8");
39 | c = 4096;
40 | dkLen = 20;
41 | DK = "4b007901b765489abead49d926f721d065a429c1";
42 |
43 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
44 |
45 | P = "password".getBytes("UTF-8");
46 | S = "salt".getBytes("UTF-8");
47 | c = 16777216;
48 | dkLen = 20;
49 | DK = "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984";
50 |
51 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
52 |
53 | P = "passwordPASSWORDpassword".getBytes("UTF-8");
54 | S = "saltSALTsaltSALTsaltSALTsaltSALTsalt".getBytes("UTF-8");
55 | c = 4096;
56 | dkLen = 25;
57 | DK = "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038";
58 |
59 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
60 |
61 | P = "pass\0word".getBytes("UTF-8");
62 | S = "sa\0lt".getBytes("UTF-8");
63 | c = 4096;
64 | dkLen = 16;
65 | DK = "56fa6aa75548099dcc37d7f03425e0c3";
66 |
67 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
68 | }
69 |
70 | @Test
71 | public void pbkdf2_hmac_sha1_rfc3962() throws Exception {
72 | String alg = "HmacSHA1";
73 | byte[] P, S;
74 | int c, dkLen;
75 | String DK;
76 |
77 | P = "password".getBytes("UTF-8");
78 | S = "ATHENA.MIT.EDUraeburn".getBytes("UTF-8");
79 | c = 1;
80 |
81 | dkLen = 16;
82 | DK = "cdedb5281bb2f801565a1122b2563515";
83 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
84 |
85 | dkLen = 32;
86 | DK = "cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837";
87 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
88 |
89 | P = "password".getBytes("UTF-8");
90 | S = "ATHENA.MIT.EDUraeburn".getBytes("UTF-8");
91 | c = 2;
92 |
93 | dkLen = 16;
94 | DK = "01dbee7f4a9e243e988b62c73cda935d";
95 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
96 |
97 | dkLen = 32;
98 | DK = "01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86";
99 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
100 |
101 | P = "password".getBytes("UTF-8");
102 | S = "ATHENA.MIT.EDUraeburn".getBytes("UTF-8");
103 | c = 1200;
104 |
105 | dkLen = 16;
106 | DK = "5c08eb61fdf71e4e4ec3cf6ba1f5512b";
107 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
108 |
109 | dkLen = 32;
110 | DK = "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13";
111 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
112 |
113 | P = "password".getBytes("UTF-8");
114 | S = new BigInteger("1234567878563412", 16).toByteArray();
115 | c = 5;
116 |
117 | dkLen = 16;
118 | DK = "d1daa78615f287e6a1c8b120d7062a49";
119 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
120 |
121 | dkLen = 32;
122 | DK = "d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee";
123 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
124 | }
125 |
126 | @Test
127 | public void pbkdf2_hmac_sha256_scrypt() throws Exception {
128 | String alg = "HmacSHA256";
129 | byte[] P, S;
130 | int c, dkLen;
131 | String DK;
132 |
133 | P = "password".getBytes("UTF-8");
134 | S = "salt".getBytes("UTF-8");
135 | c = 4096;
136 | dkLen = 32;
137 | DK = "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a";
138 |
139 | assertArrayEquals(decode(DK), PBKDF.pbkdf2(alg, P, S, c, dkLen));
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/com/lambdaworks/crypto/SCrypt.java:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2011 - Will Glozer. All rights reserved.
2 |
3 | package com.lambdaworks.crypto;
4 |
5 | import javax.crypto.Mac;
6 | import javax.crypto.spec.SecretKeySpec;
7 | import java.security.GeneralSecurityException;
8 |
9 | import static java.lang.Integer.MAX_VALUE;
10 | import static java.lang.System.arraycopy;
11 |
12 | /**
13 | * An implementation of the scrypt
14 | * key derivation function. This class will attempt to load a native library
15 | * containing the optimized C implementation from
16 | * http://www.tarsnap.com/scrypt.html and
17 | * fall back to the pure Java version if that fails.
18 | *
19 | * @author Will Glozer
20 | */
21 | public class SCrypt {
22 | private static boolean native_library_loaded = false;
23 |
24 |
25 |
26 | /**
27 | * Implementation of the scrypt KDF.
28 | * Calls the native implementation {@link #scryptN} when the native library was successfully
29 | * loaded, otherwise calls {@link #scryptJ}.
30 | *
31 | * @param passwd Password.
32 | * @param salt Salt.
33 | * @param N CPU cost parameter.
34 | * @param r Memory cost parameter.
35 | * @param p Parallelization parameter.
36 | * @param dkLen Intended length of the derived key.
37 | *
38 | * @return The derived key.
39 | *
40 | * @throws GeneralSecurityException when HMAC_SHA256 is not available.
41 | */
42 | public static byte[] scrypt(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen) throws GeneralSecurityException {
43 | return native_library_loaded ? scryptN(passwd, salt, N, r, p, dkLen) : scryptJ(passwd, salt, N, r, p, dkLen);
44 | }
45 |
46 | /**
47 | * Native C implementation of the scrypt KDF using
48 | * the code from http://www.tarsnap.com/scrypt.html.
49 | *
50 | * @param passwd Password.
51 | * @param salt Salt.
52 | * @param N CPU cost parameter.
53 | * @param r Memory cost parameter.
54 | * @param p Parallelization parameter.
55 | * @param dkLen Intended length of the derived key.
56 | *
57 | * @return The derived key.
58 | */
59 | public static native byte[] scryptN(byte[] passwd, byte[] salt, long N, int r, int p, int dkLen);
60 |
61 | /**
62 | * Pure Java implementation of the scrypt KDF.
63 | *
64 | * @param passwd Password.
65 | * @param salt Salt.
66 | * @param N CPU cost parameter.
67 | * @param r Memory cost parameter.
68 | * @param p Parallelization parameter.
69 | * @param dkLen Intended length of the derived key.
70 | *
71 | * @return The derived key.
72 | *
73 | * @throws GeneralSecurityException when HMAC_SHA256 is not available.
74 | */
75 | public static byte[] scryptJ(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen) throws GeneralSecurityException {
76 | if (N == 0 || (N & (N - 1)) != 0) throw new IllegalArgumentException("N must be > 0 and a power of 2");
77 |
78 | if (N > MAX_VALUE / 128 / r) throw new IllegalArgumentException("Parameter N is too large");
79 | if (r > MAX_VALUE / 128 / p) throw new IllegalArgumentException("Parameter r is too large");
80 |
81 | Mac mac = Mac.getInstance("HmacSHA256");
82 | mac.init(new SecretKeySpec(passwd, "HmacSHA256"));
83 |
84 | byte[] DK = new byte[dkLen];
85 |
86 | byte[] B = new byte[128 * r * p];
87 | byte[] XY = new byte[256 * r];
88 | byte[] V = new byte[128 * r * N];
89 | int i;
90 |
91 | PBKDF.pbkdf2(mac, salt, 1, B, p * 128 * r);
92 |
93 | for (i = 0; i < p; i++) {
94 | smix(B, i * 128 * r, r, N, V, XY);
95 | }
96 |
97 | PBKDF.pbkdf2(mac, B, 1, DK, dkLen);
98 |
99 | return DK;
100 | }
101 |
102 | public static void smix(byte[] B, int Bi, int r, int N, byte[] V, byte[] XY) {
103 | int Xi = 0;
104 | int Yi = 128 * r;
105 | int i;
106 |
107 | arraycopy(B, Bi, XY, Xi, 128 * r);
108 |
109 | for (i = 0; i < N; i++) {
110 | arraycopy(XY, Xi, V, i * (128 * r), 128 * r);
111 | blockmix_salsa8(XY, Xi, Yi, r);
112 | }
113 |
114 | for (i = 0; i < N; i++) {
115 | int j = integerify(XY, Xi, r) & (N - 1);
116 | blockxor(V, j * (128 * r), XY, Xi, 128 * r);
117 | blockmix_salsa8(XY, Xi, Yi, r);
118 | }
119 |
120 | arraycopy(XY, Xi, B, Bi, 128 * r);
121 | }
122 |
123 | public static void blockmix_salsa8(byte[] BY, int Bi, int Yi, int r) {
124 | byte[] X = new byte[64];
125 | int i;
126 |
127 | arraycopy(BY, Bi + (2 * r - 1) * 64, X, 0, 64);
128 |
129 | for (i = 0; i < 2 * r; i++) {
130 | blockxor(BY, i * 64, X, 0, 64);
131 | salsa20_8(X);
132 | arraycopy(X, 0, BY, Yi + (i * 64), 64);
133 | }
134 |
135 | for (i = 0; i < r; i++) {
136 | arraycopy(BY, Yi + (i * 2) * 64, BY, Bi + (i * 64), 64);
137 | }
138 |
139 | for (i = 0; i < r; i++) {
140 | arraycopy(BY, Yi + (i * 2 + 1) * 64, BY, Bi + (i + r) * 64, 64);
141 | }
142 | }
143 |
144 | public static int R(int a, int b) {
145 | return (a << b) | (a >>> (32 - b));
146 | }
147 |
148 | public static void salsa20_8(byte[] B) {
149 | int[] B32 = new int[16];
150 | int[] x = new int[16];
151 | int i;
152 |
153 | for (i = 0; i < 16; i++) {
154 | B32[i] = (B[i * 4 + 0] & 0xff) << 0;
155 | B32[i] |= (B[i * 4 + 1] & 0xff) << 8;
156 | B32[i] |= (B[i * 4 + 2] & 0xff) << 16;
157 | B32[i] |= (B[i * 4 + 3] & 0xff) << 24;
158 | }
159 |
160 | arraycopy(B32, 0, x, 0, 16);
161 |
162 | for (i = 8; i > 0; i -= 2) {
163 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
164 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
165 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
166 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
167 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
168 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
169 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
170 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
171 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
172 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
173 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
174 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
175 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
176 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
177 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
178 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
179 | }
180 |
181 | for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i];
182 |
183 | for (i = 0; i < 16; i++) {
184 | B[i * 4 + 0] = (byte) (B32[i] >> 0 & 0xff);
185 | B[i * 4 + 1] = (byte) (B32[i] >> 8 & 0xff);
186 | B[i * 4 + 2] = (byte) (B32[i] >> 16 & 0xff);
187 | B[i * 4 + 3] = (byte) (B32[i] >> 24 & 0xff);
188 | }
189 | }
190 |
191 | public static void blockxor(byte[] S, int Si, byte[] D, int Di, int len) {
192 | for (int i = 0; i < len; i++) {
193 | D[Di + i] ^= S[Si + i];
194 | }
195 | }
196 |
197 | public static int integerify(byte[] B, int Bi, int r) {
198 | int n;
199 |
200 | Bi += (2 * r - 1) * 64;
201 |
202 | n = (B[Bi + 0] & 0xff) << 0;
203 | n |= (B[Bi + 1] & 0xff) << 8;
204 | n |= (B[Bi + 2] & 0xff) << 16;
205 | n |= (B[Bi + 3] & 0xff) << 24;
206 |
207 | return n;
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/src/com/dvanderbleek/miner/Miner.java:
--------------------------------------------------------------------------------
1 | package com.dvanderbleek.miner;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStreamReader;
6 | import java.io.OutputStreamWriter;
7 | import java.math.BigInteger;
8 | import java.net.Authenticator;
9 | import java.net.PasswordAuthentication;
10 | import java.net.URL;
11 | import java.net.URLConnection;
12 | import java.security.GeneralSecurityException;
13 |
14 |
15 | import com.google.gson.Gson;
16 | import com.lambdaworks.crypto.SCrypt;
17 |
18 |
19 |
20 | public class Miner {
21 |
22 | /**
23 | * @param args
24 | * @throws GeneralSecurityException
25 | * @throws IOException
26 | */
27 | public static void main(String[] args) throws GeneralSecurityException, IOException {
28 |
29 | final String rpcuser ="user"; //RPC User name (set in config)
30 | final String rpcpassword ="x"; //RPC Pass (set in config)
31 |
32 | Authenticator.setDefault(new Authenticator() {//This sets the default authenticator, with the set username and password
33 | protected PasswordAuthentication getPasswordAuthentication() {
34 | return new PasswordAuthentication (rpcuser, rpcpassword.toCharArray());
35 | }
36 | });
37 | while(true){
38 | Work work = getwork(); //Gets the work from the server
39 | String data = work.result.data; //Gets the data to hash from the work
40 | String target = work.result.target;//Gets the target from the work
41 |
42 | //This chunk pulls apart the data so they can be endian switched (see the scrypt proof of work page on the wiki)
43 | String version = data.substring(0, 8);
44 | String prevhash = data.substring(8, 72);
45 | String merkle = data.substring(72, 136 );
46 | String timestamp = data.substring(136, 144);
47 | String bits = data.substring(144, 152);
48 | String nonce = data.substring(152,160);
49 |
50 | //This chunk creates endian switched byte arrays from the data
51 | byte[] versionbit = chunkEndianSwitch(Converter.fromHexString(version));
52 | byte[] prevhashbit = chunkEndianSwitch(Converter.fromHexString(prevhash));
53 | byte[] merklebit = chunkEndianSwitch(Converter.fromHexString(merkle));
54 | byte[] timestampbit = chunkEndianSwitch(Converter.fromHexString(timestamp));
55 | byte[] bitsbit = chunkEndianSwitch(Converter.fromHexString(bits));
56 | byte[] noncebit = chunkEndianSwitch(Converter.fromHexString(nonce));
57 |
58 | //This chunk of code reassembles the data into a single byre array
59 | byte[] databyte = new byte[80];
60 | System.arraycopy(versionbit, 0, databyte, 0, versionbit.length);
61 | System.arraycopy(prevhashbit, 0, databyte, 4, prevhashbit.length);
62 | System.arraycopy(merklebit, 0, databyte, 36, merklebit.length);
63 | System.arraycopy(timestampbit, 0, databyte, 68, timestampbit.length);
64 | System.arraycopy(bitsbit, 0, databyte, 72, bitsbit.length);
65 | System.arraycopy(noncebit, 0, databyte, 76, noncebit.length);
66 |
67 | //Converts the target string to a byte array for easier comparison
68 | byte[] targetbyte = Converter.fromHexString(target);
69 | targetbyte = endianSwitch(targetbyte);
70 |
71 | byte[] scrypted = doScrypt(databyte, targetbyte);//Calls sCrypt with the proper parameters, and returns the correct data
72 | byte[] databyte2 = Converter.fromHexString(data);
73 | System.arraycopy(chunkEndianSwitch(scrypted), 0, databyte2, 76, scrypted.length);
74 |
75 | work.result.data = printByteArray(databyte2);
76 | System.out.println(sendWork(work));//Send the work
77 | }
78 | }
79 |
80 | public static byte[] doScrypt(byte[] databyte, byte[] target) throws GeneralSecurityException{
81 | //Initialize the nonce
82 | byte[] nonce = new byte[4];
83 | nonce[0] = databyte[76] ;
84 | nonce[1] = databyte[77] ;
85 | nonce[2] = databyte[78] ;
86 | nonce[3] = databyte[79] ;
87 | boolean found = false;
88 | //Loop over and increment nonce
89 | while(!found){
90 | //Set the bytes of the data to the nonce
91 | databyte[76] = nonce[0];
92 | databyte[77] = nonce[1];
93 | databyte[78] = nonce[2];
94 | databyte[79] = nonce[3];
95 |
96 | byte[] scrypted = (SCrypt.scryptJ(databyte,databyte, 1024, 1, 1, 32));//Scrypt the data with proper params
97 |
98 | BigInteger bigScrypt = new BigInteger(printByteArray(endianSwitch(scrypted)), 16); //Create a bigInteger to compare against the target
99 | BigInteger bigTarget = new BigInteger(printByteArray(target),16);//Create a bigInteger from the target
100 | if(bigScrypt.compareTo(bigTarget) == -1){
101 | System.out.println(printByteArray(scrypted));
102 | return nonce;//Compare the two bigIntegers, return the data with nonce if smaller
103 | }
104 |
105 | else incrementAtIndex(nonce, nonce.length-1); //Otherwise increment the nonce
106 |
107 | }
108 | return nonce;
109 | }
110 |
111 |
112 | public static void incrementAtIndex(byte[] array, int index) {
113 | //Short method to increment the nonce
114 | if (array[index] == Byte.MAX_VALUE) {
115 | array[index] = 0;
116 | if(index > 0)
117 | incrementAtIndex(array, index - 1);
118 | }
119 | else {
120 | array[index]++;
121 | }
122 | }
123 |
124 |
125 | public static String prettyPrintByteArray(byte[] bites){
126 | //Method to convert a byte array to hex literal separated by bites.
127 | String str = "";
128 | int n = 0;
129 | for(byte bite:bites){
130 | n += 1;
131 | str = str + (Integer.toString( ( bite & 0xff ) + 0x100, 16 /* radix */ ).substring( 1 )) + " ";
132 | if((n%16) == 0) { str += "\n"; }
133 | else if((n%4) == 0) { str += " "; }
134 | }
135 | return str;
136 | }
137 |
138 | public static String printByteArray(byte[] bites){
139 | //Method to convert a byte array to hex literal
140 | String str = "";
141 | for(byte bite:bites){
142 | str = str + (Integer.toString( ( bite & 0xff ) + 0x100, 16 /* radix */ ).substring( 1 ));
143 | }
144 | return str;
145 | }
146 |
147 | public static byte[] endianSwitch(byte[] bytes) {
148 | //Method to switch the endianess of a byte array
149 | byte[] bytes2 = new byte[bytes.length];
150 | for(int i = 0; i < bytes.length; i++){
151 | bytes2[i] = bytes[bytes.length-i-1];
152 | }
153 | return bytes2;
154 | }
155 |
156 | public static byte[] chunkEndianSwitch(byte[] bytes) {
157 | //Method to properly switch the endianness of the header -- numbers must be treated as 32 bit chunks. Thanks to ali1234 for this.
158 | byte[] bytes2 = new byte[bytes.length];
159 | for(int i = 0; i < bytes.length; i+=4){
160 | bytes2[i] = bytes[i+3];
161 | bytes2[i+1] = bytes[i+2];
162 | bytes2[i+2] = bytes[i+1];
163 | bytes2[i+3] = bytes[i];
164 | }
165 | return bytes2;
166 | }
167 |
168 |
169 | public static Work getwork() throws IOException{
170 | //Method to getwork
171 | URL url = new URL("http://127.0.0.1:9332");
172 | URLConnection conn = url.openConnection();
173 | conn.setDoOutput(true);
174 | conn.setDoInput(true);
175 | OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
176 | String rpcreturn = "{\"jsonrpc\": \"1.0\" , \"method\": \"getwork\" }";//JSON RPC call for getting work
177 | wr.write(rpcreturn);
178 | wr.flush();
179 | BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
180 | String line;
181 |
182 | line = rd.readLine();
183 | rd.close();
184 | Gson gson = new Gson();
185 | Work work = gson.fromJson(line, Work.class);//Use GSON to create a work object from the response
186 | return work;
187 | }
188 |
189 | public static String sendWork(Work work) throws IOException{
190 | //Very similar to getwork method
191 | URL url = new URL("http://127.0.0.1:9332");
192 | URLConnection conn = url.openConnection();
193 | conn.setDoOutput(true);
194 | conn.setDoInput(true);
195 | OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
196 | System.out.println(work.result.data);
197 | String rpcreturn = "{\"jsonrpc\": \"1.0\" , \"method\": \"getwork\" , \"params\" : [\"" +work.result.data+ "\"]}";//RPC call with the new nonced data
198 | System.out.println(rpcreturn);
199 | wr.write(rpcreturn);
200 | wr.flush();
201 | BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
202 | String line;
203 | line = rd.readLine();
204 | rd.close();
205 | return line;
206 | }
207 | }
--------------------------------------------------------------------------------
/src/com/dvanderbleek/miner/Converter.java:
--------------------------------------------------------------------------------
1 | package com.dvanderbleek.miner;
2 |
3 | public class Converter {
4 |
5 | /* ========================= */
6 | /* "primitive type --> byte[] data" Methods */
7 | /* ========================= */
8 |
9 | public static byte[] toByta(byte data) {
10 | return new byte[]{data};
11 | }
12 |
13 | public static byte[] toByta(byte[] data) {
14 | return data;
15 | }
16 |
17 | /* ========================= */
18 |
19 | public static byte[] toByta(short data) {
20 | return new byte[] {
21 | (byte)((data >> 8) & 0xff),
22 | (byte)((data >> 0) & 0xff),
23 | };
24 | }
25 |
26 | public static byte[] toByta(short[] data) {
27 | if (data == null) return null;
28 | // ----------
29 | byte[] byts = new byte[data.length * 2];
30 | for (int i = 0; i < data.length; i++)
31 | System.arraycopy(toByta(data[i]), 0, byts, i * 2, 2);
32 | return byts;
33 | }
34 |
35 | /* ========================= */
36 |
37 | public static byte[] toByta(char data) {
38 | return new byte[] {
39 | (byte)((data >> 8) & 0xff),
40 | (byte)((data >> 0) & 0xff),
41 | };
42 | }
43 |
44 | public static byte[] toByta(char[] data) {
45 | if (data == null) return null;
46 | // ----------
47 | byte[] byts = new byte[data.length * 2];
48 | for (int i = 0; i < data.length; i++)
49 | System.arraycopy(toByta(data[i]), 0, byts, i * 2, 2);
50 | return byts;
51 | }
52 |
53 | /* ========================= */
54 |
55 | public static byte[] toByta(int data) {
56 | return new byte[] {
57 | (byte)((data >> 24) & 0xff),
58 | (byte)((data >> 16) & 0xff),
59 | (byte)((data >> 8) & 0xff),
60 | (byte)((data >> 0) & 0xff),
61 | };
62 | }
63 |
64 | public static byte[] toByta(int[] data) {
65 | if (data == null) return null;
66 | // ----------
67 | byte[] byts = new byte[data.length * 4];
68 | for (int i = 0; i < data.length; i++)
69 | System.arraycopy(toByta(data[i]), 0, byts, i * 4, 4);
70 | return byts;
71 | }
72 |
73 | /* ========================= */
74 |
75 | public static byte[] toByta(long data) {
76 | return new byte[] {
77 | (byte)((data >> 56) & 0xff),
78 | (byte)((data >> 48) & 0xff),
79 | (byte)((data >> 40) & 0xff),
80 | (byte)((data >> 32) & 0xff),
81 | (byte)((data >> 24) & 0xff),
82 | (byte)((data >> 16) & 0xff),
83 | (byte)((data >> 8) & 0xff),
84 | (byte)((data >> 0) & 0xff),
85 | };
86 | }
87 |
88 | public static byte[] toByta(long[] data) {
89 | if (data == null) return null;
90 | // ----------
91 | byte[] byts = new byte[data.length * 8];
92 | for (int i = 0; i < data.length; i++)
93 | System.arraycopy(toByta(data[i]), 0, byts, i * 8, 8);
94 | return byts;
95 | }
96 |
97 | /* ========================= */
98 |
99 | public static byte[] toByta(float data) {
100 | return toByta(Float.floatToRawIntBits(data));
101 | }
102 |
103 | public static byte[] toByta(float[] data) {
104 | if (data == null) return null;
105 | // ----------
106 | byte[] byts = new byte[data.length * 4];
107 | for (int i = 0; i < data.length; i++)
108 | System.arraycopy(toByta(data[i]), 0, byts, i * 4, 4);
109 | return byts;
110 | }
111 |
112 | /* ========================= */
113 |
114 | public static byte[] toByta(double data) {
115 | return toByta(Double.doubleToRawLongBits(data));
116 | }
117 |
118 | public static byte[] toByta(double[] data) {
119 | if (data == null) return null;
120 | // ----------
121 | byte[] byts = new byte[data.length * 8];
122 | for (int i = 0; i < data.length; i++)
123 | System.arraycopy(toByta(data[i]), 0, byts, i * 8, 8);
124 | return byts;
125 | }
126 |
127 | /* ========================= */
128 |
129 | public static byte[] toByta(boolean data) {
130 | return new byte[]{(byte)(data ? 0x01 : 0x00)}; // bool -> {1 byte}
131 | }
132 |
133 | public static byte[] toByta(boolean[] data) {
134 | // Advanced Technique: The byte array containts information
135 | // about how many boolean values are involved, so the exact
136 | // array is returned when later decoded.
137 | // ----------
138 | if (data == null) return null;
139 | // ----------
140 | int len = data.length;
141 | byte[] lena = toByta(len); // int conversion; length array = lena
142 | byte[] byts = new byte[lena.length + (len / 8) + (len % 8 != 0 ? 1 : 0)];
143 | // (Above) length-array-length + sets-of-8-booleans +? byte-for-remainder
144 | System.arraycopy(lena, 0, byts, 0, lena.length);
145 | // ----------
146 | // (Below) algorithm by Matthew Cudmore: boolean[] -> bits -> byte[]
147 | for (int i = 0, j = lena.length, k = 7; i < data.length; i++) {
148 | byts[j] |= (data[i] ? 1 : 0) << k--;
149 | if (k < 0) { j++; k = 7; }
150 | }
151 | // ----------
152 | return byts;
153 | }
154 |
155 | /* ========================= */
156 |
157 | public static byte[] toByta(String data) {
158 | return (data == null) ? null : data.getBytes();
159 | }
160 |
161 | public static byte[] toByta(String[] data) {
162 | // Advanced Technique: Generates an indexed byte array
163 | // which contains the array of Strings. The byte array
164 | // contains information about the number of Strings and
165 | // the length of each String.
166 | // ----------
167 | if (data == null) return null;
168 | // ---------- flags:
169 | int totalLength = 0; // Measure length of final byte array
170 | int bytesPos = 0; // Used later
171 | // ----- arrays:
172 | byte[] dLen = toByta(data.length); // byte array of data length
173 | totalLength += dLen.length;
174 | int[] sLens = new int[data.length]; // String lengths = sLens
175 | totalLength += (sLens.length * 4);
176 | byte[][] strs = new byte[data.length][]; // array of String bytes
177 | // ----- pack strs:
178 | for (int i = 0; i < data.length; i++) {
179 | if (data[i] != null) {
180 | strs[i] = toByta(data[i]);
181 | sLens[i] = strs[i].length;
182 | totalLength += strs[i].length;
183 | } else {
184 | sLens[i] = 0;
185 | strs[i] = new byte[0]; // prevent null entries
186 | }
187 | }
188 | // ----------
189 | byte[] bytes = new byte[totalLength]; // final array
190 | System.arraycopy(dLen, 0, bytes, 0, 4);
191 | byte[] bsLens = toByta(sLens); // byte version of String sLens
192 | System.arraycopy(bsLens, 0, bytes, 4, bsLens.length);
193 | // -----
194 | bytesPos += 4 + bsLens.length; // mark position
195 | // -----
196 | for (byte[] sba : strs) {
197 | System.arraycopy(sba, 0, bytes, bytesPos, sba.length);
198 | bytesPos += sba.length;
199 | }
200 | // ----------
201 | return bytes;
202 | }
203 |
204 | /* ========================= */
205 | /* "byte[] data --> primitive type" Methods */
206 | /* ========================= */
207 |
208 | public static byte toByte(byte[] data) {
209 | return (data == null || data.length == 0) ? 0x0 : data[0];
210 | }
211 |
212 | public static byte[] toByteA(byte[] data) {
213 | return data;
214 | }
215 |
216 | /* ========================= */
217 |
218 | public static short toShort(byte[] data) {
219 | if (data == null || data.length != 2) return 0x0;
220 | // ----------
221 | return (short)(
222 | (0xff & data[0]) << 8 |
223 | (0xff & data[1]) << 0
224 | );
225 | }
226 |
227 | public static short[] toShortA(byte[] data) {
228 | if (data == null || data.length % 2 != 0) return null;
229 | // ----------
230 | short[] shts = new short[data.length / 2];
231 | for (int i = 0; i < shts.length; i++) {
232 | shts[i] = toShort( new byte[] {
233 | data[(i*2)],
234 | data[(i*2)+1]
235 | } );
236 | }
237 | return shts;
238 | }
239 |
240 | /* ========================= */
241 |
242 | public static char toChar(byte[] data) {
243 | if (data == null || data.length != 2) return 0x0;
244 | // ----------
245 | return (char)(
246 | (0xff & data[0]) << 8 |
247 | (0xff & data[1]) << 0
248 | );
249 | }
250 |
251 | public static char[] toCharA(byte[] data) {
252 | if (data == null || data.length % 2 != 0) return null;
253 | // ----------
254 | char[] chrs = new char[data.length / 2];
255 | for (int i = 0; i < chrs.length; i++) {
256 | chrs[i] = toChar( new byte[] {
257 | data[(i*2)],
258 | data[(i*2)+1],
259 | } );
260 | }
261 | return chrs;
262 | }
263 |
264 | /* ========================= */
265 |
266 | public static int toInt(byte[] data) {
267 | if (data == null || data.length != 4) return 0x0;
268 | // ----------
269 | return (int)( // NOTE: type cast not necessary for int
270 | (0xff & data[0]) << 24 |
271 | (0xff & data[1]) << 16 |
272 | (0xff & data[2]) << 8 |
273 | (0xff & data[3]) << 0
274 | );
275 | }
276 |
277 | public static int[] toIntA(byte[] data) {
278 | if (data == null || data.length % 4 != 0) return null;
279 | // ----------
280 | int[] ints = new int[data.length / 4];
281 | for (int i = 0; i < ints.length; i++)
282 | ints[i] = toInt( new byte[] {
283 | data[(i*4)],
284 | data[(i*4)+1],
285 | data[(i*4)+2],
286 | data[(i*4)+3],
287 | } );
288 | return ints;
289 | }
290 |
291 | /* ========================= */
292 |
293 | public static long toLong(byte[] data) {
294 | if (data == null || data.length != 8) return 0x0;
295 | // ----------
296 | return (long)(
297 | // (Below) convert to longs before shift because digits
298 | // are lost with ints beyond the 32-bit limit
299 | (long)(0xff & data[0]) << 56 |
300 | (long)(0xff & data[1]) << 48 |
301 | (long)(0xff & data[2]) << 40 |
302 | (long)(0xff & data[3]) << 32 |
303 | (long)(0xff & data[4]) << 24 |
304 | (long)(0xff & data[5]) << 16 |
305 | (long)(0xff & data[6]) << 8 |
306 | (long)(0xff & data[7]) << 0
307 | );
308 | }
309 |
310 | public static long[] toLongA(byte[] data) {
311 | if (data == null || data.length % 8 != 0) return null;
312 | // ----------
313 | long[] lngs = new long[data.length / 8];
314 | for (int i = 0; i < lngs.length; i++) {
315 | lngs[i] = toLong( new byte[] {
316 | data[(i*8)],
317 | data[(i*8)+1],
318 | data[(i*8)+2],
319 | data[(i*8)+3],
320 | data[(i*8)+4],
321 | data[(i*8)+5],
322 | data[(i*8)+6],
323 | data[(i*8)+7],
324 | } );
325 | }
326 | return lngs;
327 | }
328 |
329 | /* ========================= */
330 |
331 | public static float toFloat(byte[] data) {
332 | if (data == null || data.length != 4) return 0x0;
333 | // ---------- simple:
334 | return Float.intBitsToFloat(toInt(data));
335 | }
336 |
337 | public static float[] toFloatA(byte[] data) {
338 | if (data == null || data.length % 4 != 0) return null;
339 | // ----------
340 | float[] flts = new float[data.length / 4];
341 | for (int i = 0; i < flts.length; i++) {
342 | flts[i] = toFloat( new byte[] {
343 | data[(i*4)],
344 | data[(i*4)+1],
345 | data[(i*4)+2],
346 | data[(i*4)+3],
347 | } );
348 | }
349 | return flts;
350 | }
351 |
352 | /* ========================= */
353 |
354 | public static double toDouble(byte[] data) {
355 | if (data == null || data.length != 8) return 0x0;
356 | // ---------- simple:
357 | return Double.longBitsToDouble(toLong(data));
358 | }
359 |
360 | public static double[] toDoubleA(byte[] data) {
361 | if (data == null) return null;
362 | // ----------
363 | if (data.length % 8 != 0) return null;
364 | double[] dbls = new double[data.length / 8];
365 | for (int i = 0; i < dbls.length; i++) {
366 | dbls[i] = toDouble( new byte[] {
367 | data[(i*8)],
368 | data[(i*8)+1],
369 | data[(i*8)+2],
370 | data[(i*8)+3],
371 | data[(i*8)+4],
372 | data[(i*8)+5],
373 | data[(i*8)+6],
374 | data[(i*8)+7],
375 | } );
376 | }
377 | return dbls;
378 | }
379 |
380 | /* ========================= */
381 |
382 | public static boolean toBoolean(byte[] data) {
383 | return (data == null || data.length == 0) ? false : data[0] != 0x00;
384 | }
385 |
386 | public static boolean[] toBooleanA(byte[] data) {
387 | // Advanced Technique: Extract the boolean array's length
388 | // from the first four bytes in the char array, and then
389 | // read the boolean array.
390 | // ----------
391 | if (data == null || data.length < 4) return null;
392 | // ----------
393 | int len = toInt(new byte[]{data[0], data[1], data[2], data[3]});
394 | boolean[] bools = new boolean[len];
395 | // ----- pack bools:
396 | for (int i = 0, j = 4, k = 7; i < bools.length; i++) {
397 | bools[i] = ((data[j] >> k--) & 0x01) == 1;
398 | if (k < 0) { j++; k = 7; }
399 | }
400 | // ----------
401 | return bools;
402 | }
403 |
404 | /* ========================= */
405 |
406 | public static String toString(byte[] data) {
407 | return (data == null) ? null : new String(data);
408 | }
409 |
410 | public static String[] toStringA(byte[] data) {
411 | // Advanced Technique: Extract the String array's length
412 | // from the first four bytes in the char array, and then
413 | // read the int array denoting the String lengths, and
414 | // then read the Strings.
415 | // ----------
416 | if (data == null || data.length < 4) return null;
417 | // ----------
418 | byte[] bBuff = new byte[4]; // Buffer
419 | // -----
420 | System.arraycopy(data, 0, bBuff, 0, 4);
421 | int saLen = toInt(bBuff);
422 | if (data.length < (4 + (saLen * 4))) return null;
423 | // -----
424 | bBuff = new byte[saLen * 4];
425 | System.arraycopy(data, 4, bBuff, 0, bBuff.length);
426 | int[] sLens = toIntA(bBuff);
427 | if (sLens == null) return null;
428 | // ----------
429 | String[] strs = new String[saLen];
430 | for (int i = 0, dataPos = 4 + (saLen * 4); i < saLen; i++) {
431 | if (sLens[i] > 0) {
432 | if (data.length >= (dataPos + sLens[i])) {
433 | bBuff = new byte[sLens[i]];
434 | System.arraycopy(data, dataPos, bBuff, 0, sLens[i]);
435 | dataPos += sLens[i];
436 | strs[i] = toString(bBuff);
437 | } else return null;
438 | }
439 | }
440 | // ----------
441 | return strs;
442 | }
443 |
444 | private static final byte[] correspondingNibble = new byte[ 'f' + 1 ];
445 |
446 | // -------------------------- STATIC METHODS --------------------------
447 |
448 | static
449 | {
450 | // only 0..9 A..F a..f have meaning. rest are errors.
451 | for ( int i = 0; i <= 'f'; i++ )
452 | {
453 | correspondingNibble[ i ] = -1;
454 | }
455 | for ( int i = '0'; i <= '9'; i++ )
456 | {
457 | correspondingNibble[ i ] = ( byte ) ( i - '0' );
458 | }
459 | for ( int i = 'A'; i <= 'F'; i++ )
460 | {
461 | correspondingNibble[ i ] = ( byte ) ( i - 'A' + 10 );
462 | }
463 | for ( int i = 'a'; i <= 'f'; i++ )
464 | {
465 | correspondingNibble[ i ] = ( byte ) ( i - 'a' + 10 );
466 | }
467 | }
468 |
469 | /**
470 | * convert a single char to corresponding nibble using a precalculated array.
471 | * Based on code by:
472 | * Brian Marquis
473 | * Orion Group Software Engineers http://www.ogse.com
474 | *
475 | * @param c char to convert. must be 0-9 a-f A-F, no
476 | * spaces, plus or minus signs.
477 | *
478 | * @return corresponding integer 0..15
479 | * @throws IllegalArgumentException on invalid c.
480 | */
481 | private static int charToNibble( char c )
482 | {
483 | if ( c > 'f' )
484 | {
485 | throw new IllegalArgumentException( "Invalid hex character: " + c );
486 | }
487 | int nibble = correspondingNibble[ c ];
488 | if ( nibble < 0 )
489 | {
490 | throw new IllegalArgumentException( "Invalid hex character: " + c );
491 | }
492 | return nibble;
493 | }
494 |
495 | /**
496 | * Convert a hex string to an unsigned byte array.
497 | * Permits upper or lower case hex.
498 | *
499 | * @param s String must have even number of characters.
500 | * and be formed only of digits 0-9 A-F or
501 | * a-f. No spaces, minus or plus signs.
502 | *
503 | * @return corresponding unsigned byte array. see http://mindprod.com/jgloss/unsigned.html
504 | */
505 | static byte[] fromHexString( String s )
506 | {
507 | int stringLength = s.length();
508 | if ( ( stringLength & 0x1 ) != 0 )
509 | {
510 | throw new IllegalArgumentException( "fromHexString requires an even number of hex characters" );
511 | }
512 | byte[] bytes = new byte[ stringLength / 2 ];
513 | for ( int i = 0, j = 0; i < stringLength; i += 2, j++ )
514 | {
515 | int high = charToNibble( s.charAt( i ) );
516 | int low = charToNibble( s.charAt( i + 1 ) );
517 | // You can store either unsigned 0..255 or signed -128..127 bytes in a byte type.
518 | bytes[ j ] = ( byte ) ( ( high << 4 ) | low );
519 | }
520 | return bytes;
521 | }
522 | }
523 |
--------------------------------------------------------------------------------
/src/com/lambdaworks/crypto/Base64.java:
--------------------------------------------------------------------------------
1 | package com.lambdaworks.crypto;
2 |
3 | import java.util.Arrays;
4 |
5 | /** A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance
6 | * with RFC 2045.sun.misc.Encoder()/Decoder().String this
14 | * version is about three times as fast due to the fact that the Commons Codec result has to be recoded
15 | * to a String from byte[], which is very expensive.sun.misc.Encoder()/Decoder() produce temporary arrays but since performance
21 | * is quite low it probably does.char[] representation i accordance with RFC 2045.
89 | * @param sArr The bytes to convert. If null or length 0 an empty array will be returned.
90 | * @param lineSep Optional "\r\n" after 76 characters, unless end of file.null.
94 | */
95 | public final static char[] encodeToChar(byte[] sArr, boolean lineSep)
96 | {
97 | // Check special case
98 | int sLen = sArr != null ? sArr.length : 0;
99 | if (sLen == 0)
100 | return new char[0];
101 |
102 | int eLen = (sLen / 3) * 3; // Length of even 24-bits.
103 | int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count
104 | int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
105 | char[] dArr = new char[dLen];
106 |
107 | // Encode even 24-bits
108 | for (int s = 0, d = 0, cc = 0; s < eLen;) {
109 | // Copy next three bytes into lower 24 bits of int, paying attension to sign.
110 | int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff);
111 |
112 | // Encode the int into four chars
113 | dArr[d++] = CA[(i >>> 18) & 0x3f];
114 | dArr[d++] = CA[(i >>> 12) & 0x3f];
115 | dArr[d++] = CA[(i >>> 6) & 0x3f];
116 | dArr[d++] = CA[i & 0x3f];
117 |
118 | // Add optional line separator
119 | if (lineSep && ++cc == 19 && d < dLen - 2) {
120 | dArr[d++] = '\r';
121 | dArr[d++] = '\n';
122 | cc = 0;
123 | }
124 | }
125 |
126 | // Pad and encode last bits if source isn't even 24 bits.
127 | int left = sLen - eLen; // 0 - 2.
128 | if (left > 0) {
129 | // Prepare the int
130 | int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0);
131 |
132 | // Set last four chars
133 | dArr[dLen - 4] = CA[i >> 12];
134 | dArr[dLen - 3] = CA[(i >>> 6) & 0x3f];
135 | dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '=';
136 | dArr[dLen - 1] = '=';
137 | }
138 | return dArr;
139 | }
140 |
141 | /** Decodes a BASE64 encoded char array. All illegal characters will be ignored and can handle both arrays with
142 | * and without line separators.
143 | * @param sArr The source array. null or length 0 will return an empty array.
144 | * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters
145 | * (including '=') isn't divideable by 4. (I.e. definitely corrupted).
146 | */
147 | public final static byte[] decode(char[] sArr)
148 | {
149 | // Check special case
150 | int sLen = sArr != null ? sArr.length : 0;
151 | if (sLen == 0)
152 | return new byte[0];
153 |
154 | // Count illegal characters (including '\r', '\n') to know what size the returned array will be,
155 | // so we don't have to reallocate & copy it later.
156 | int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
157 | for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
158 | if (IA[sArr[i]] < 0)
159 | sepCnt++;
160 |
161 | // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045.
162 | if ((sLen - sepCnt) % 4 != 0)
163 | return null;
164 |
165 | int pad = 0;
166 | for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;)
167 | if (sArr[i] == '=')
168 | pad++;
169 |
170 | int len = ((sLen - sepCnt) * 6 >> 3) - pad;
171 |
172 | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
173 |
174 | for (int s = 0, d = 0; d < len;) {
175 | // Assemble three bytes into an int from four "valid" characters.
176 | int i = 0;
177 | for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
178 | int c = IA[sArr[s++]];
179 | if (c >= 0)
180 | i |= c << (18 - j * 6);
181 | else
182 | j--;
183 | }
184 | // Add the bytes
185 | dArr[d++] = (byte) (i >> 16);
186 | if (d < len) {
187 | dArr[d++]= (byte) (i >> 8);
188 | if (d < len)
189 | dArr[d++] = (byte) i;
190 | }
191 | }
192 | return dArr;
193 | }
194 |
195 | /** Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as
196 | * fast as {@link #decode(char[])}. The preconditions are:null will throw an exception.
202 | * @return The decoded array of bytes. May be of length 0.
203 | */
204 | public final static byte[] decodeFast(char[] sArr)
205 | {
206 | // Check special case
207 | int sLen = sArr.length;
208 | if (sLen == 0)
209 | return new byte[0];
210 |
211 | int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
212 |
213 | // Trim illegal chars from start
214 | while (sIx < eIx && IA[sArr[sIx]] < 0)
215 | sIx++;
216 |
217 | // Trim illegal chars from end
218 | while (eIx > 0 && IA[sArr[eIx]] < 0)
219 | eIx--;
220 |
221 | // get the padding count (=) (0, 1 or 2)
222 | int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end.
223 | int cCnt = eIx - sIx + 1; // Content count including possible separators
224 | int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
225 |
226 | int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
227 | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
228 |
229 | // Decode all but the last 0 - 2 bytes.
230 | int d = 0;
231 | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) {
232 | // Assemble three bytes into an int from four "valid" characters.
233 | int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]];
234 |
235 | // Add the bytes
236 | dArr[d++] = (byte) (i >> 16);
237 | dArr[d++] = (byte) (i >> 8);
238 | dArr[d++] = (byte) i;
239 |
240 | // If line separator, jump over it.
241 | if (sepCnt > 0 && ++cc == 19) {
242 | sIx += 2;
243 | cc = 0;
244 | }
245 | }
246 |
247 | if (d < len) {
248 | // Decode last 1-3 bytes (incl '=') into 1-3 bytes
249 | int i = 0;
250 | for (int j = 0; sIx <= eIx - pad; j++)
251 | i |= IA[sArr[sIx++]] << (18 - j * 6);
252 |
253 | for (int r = 16; d < len; r -= 8)
254 | dArr[d++] = (byte) (i >> r);
255 | }
256 |
257 | return dArr;
258 | }
259 |
260 | // ****************************************************************************************
261 | // * byte[] version
262 | // ****************************************************************************************
263 |
264 | /** Encodes a raw byte array into a BASE64 byte[] representation i accordance with RFC 2045.
265 | * @param sArr The bytes to convert. If null or length 0 an empty array will be returned.
266 | * @param lineSep Optional "\r\n" after 76 characters, unless end of file.null.
270 | */
271 | public final static byte[] encodeToByte(byte[] sArr, boolean lineSep)
272 | {
273 | // Check special case
274 | int sLen = sArr != null ? sArr.length : 0;
275 | if (sLen == 0)
276 | return new byte[0];
277 |
278 | int eLen = (sLen / 3) * 3; // Length of even 24-bits.
279 | int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count
280 | int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
281 | byte[] dArr = new byte[dLen];
282 |
283 | // Encode even 24-bits
284 | for (int s = 0, d = 0, cc = 0; s < eLen;) {
285 | // Copy next three bytes into lower 24 bits of int, paying attension to sign.
286 | int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff);
287 |
288 | // Encode the int into four chars
289 | dArr[d++] = (byte) CA[(i >>> 18) & 0x3f];
290 | dArr[d++] = (byte) CA[(i >>> 12) & 0x3f];
291 | dArr[d++] = (byte) CA[(i >>> 6) & 0x3f];
292 | dArr[d++] = (byte) CA[i & 0x3f];
293 |
294 | // Add optional line separator
295 | if (lineSep && ++cc == 19 && d < dLen - 2) {
296 | dArr[d++] = '\r';
297 | dArr[d++] = '\n';
298 | cc = 0;
299 | }
300 | }
301 |
302 | // Pad and encode last bits if source isn't an even 24 bits.
303 | int left = sLen - eLen; // 0 - 2.
304 | if (left > 0) {
305 | // Prepare the int
306 | int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0);
307 |
308 | // Set last four chars
309 | dArr[dLen - 4] = (byte) CA[i >> 12];
310 | dArr[dLen - 3] = (byte) CA[(i >>> 6) & 0x3f];
311 | dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) '=';
312 | dArr[dLen - 1] = '=';
313 | }
314 | return dArr;
315 | }
316 |
317 | /** Decodes a BASE64 encoded byte array. All illegal characters will be ignored and can handle both arrays with
318 | * and without line separators.
319 | * @param sArr The source array. Length 0 will return an empty array. null will throw an exception.
320 | * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters
321 | * (including '=') isn't divideable by 4. (I.e. definitely corrupted).
322 | */
323 | public final static byte[] decode(byte[] sArr)
324 | {
325 | // Check special case
326 | int sLen = sArr.length;
327 |
328 | // Count illegal characters (including '\r', '\n') to know what size the returned array will be,
329 | // so we don't have to reallocate & copy it later.
330 | int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
331 | for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
332 | if (IA[sArr[i] & 0xff] < 0)
333 | sepCnt++;
334 |
335 | // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045.
336 | if ((sLen - sepCnt) % 4 != 0)
337 | return null;
338 |
339 | int pad = 0;
340 | for (int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0;)
341 | if (sArr[i] == '=')
342 | pad++;
343 |
344 | int len = ((sLen - sepCnt) * 6 >> 3) - pad;
345 |
346 | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
347 |
348 | for (int s = 0, d = 0; d < len;) {
349 | // Assemble three bytes into an int from four "valid" characters.
350 | int i = 0;
351 | for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
352 | int c = IA[sArr[s++] & 0xff];
353 | if (c >= 0)
354 | i |= c << (18 - j * 6);
355 | else
356 | j--;
357 | }
358 |
359 | // Add the bytes
360 | dArr[d++] = (byte) (i >> 16);
361 | if (d < len) {
362 | dArr[d++]= (byte) (i >> 8);
363 | if (d < len)
364 | dArr[d++] = (byte) i;
365 | }
366 | }
367 |
368 | return dArr;
369 | }
370 |
371 |
372 | /** Decodes a BASE64 encoded byte array that is known to be resonably well formatted. The method is about twice as
373 | * fast as {@link #decode(byte[])}. The preconditions are:null will throw an exception.
379 | * @return The decoded array of bytes. May be of length 0.
380 | */
381 | public final static byte[] decodeFast(byte[] sArr)
382 | {
383 | // Check special case
384 | int sLen = sArr.length;
385 | if (sLen == 0)
386 | return new byte[0];
387 |
388 | int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
389 |
390 | // Trim illegal chars from start
391 | while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0)
392 | sIx++;
393 |
394 | // Trim illegal chars from end
395 | while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0)
396 | eIx--;
397 |
398 | // get the padding count (=) (0, 1 or 2)
399 | int pad = sArr[eIx] == '=' ? (sArr[eIx - 1] == '=' ? 2 : 1) : 0; // Count '=' at end.
400 | int cCnt = eIx - sIx + 1; // Content count including possible separators
401 | int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0;
402 |
403 | int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
404 | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
405 |
406 | // Decode all but the last 0 - 2 bytes.
407 | int d = 0;
408 | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) {
409 | // Assemble three bytes into an int from four "valid" characters.
410 | int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]];
411 |
412 | // Add the bytes
413 | dArr[d++] = (byte) (i >> 16);
414 | dArr[d++] = (byte) (i >> 8);
415 | dArr[d++] = (byte) i;
416 |
417 | // If line separator, jump over it.
418 | if (sepCnt > 0 && ++cc == 19) {
419 | sIx += 2;
420 | cc = 0;
421 | }
422 | }
423 |
424 | if (d < len) {
425 | // Decode last 1-3 bytes (incl '=') into 1-3 bytes
426 | int i = 0;
427 | for (int j = 0; sIx <= eIx - pad; j++)
428 | i |= IA[sArr[sIx++]] << (18 - j * 6);
429 |
430 | for (int r = 16; d < len; r -= 8)
431 | dArr[d++] = (byte) (i >> r);
432 | }
433 |
434 | return dArr;
435 | }
436 |
437 | // ****************************************************************************************
438 | // * String version
439 | // ****************************************************************************************
440 |
441 | /** Encodes a raw byte array into a BASE64 String representation i accordance with RFC 2045.
442 | * @param sArr The bytes to convert. If null or length 0 an empty array will be returned.
443 | * @param lineSep Optional "\r\n" after 76 characters, unless end of file.null.
447 | */
448 | public final static String encodeToString(byte[] sArr, boolean lineSep)
449 | {
450 | // Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower.
451 | return new String(encodeToChar(sArr, lineSep));
452 | }
453 |
454 | /** Decodes a BASE64 encoded String. All illegal characters will be ignored and can handle both strings with
455 | * and without line separators.decode(str.toCharArray()) instead. That
457 | * will create a temporary array though. This version will use str.charAt(i) to iterate the string.
458 | * @param str The source string. null or length 0 will return an empty array.
459 | * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters
460 | * (including '=') isn't divideable by 4. (I.e. definitely corrupted).
461 | */
462 | public final static byte[] decode(String str)
463 | {
464 | // Check special case
465 | int sLen = str != null ? str.length() : 0;
466 | if (sLen == 0)
467 | return new byte[0];
468 |
469 | // Count illegal characters (including '\r', '\n') to know what size the returned array will be,
470 | // so we don't have to reallocate & copy it later.
471 | int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...)
472 | for (int i = 0; i < sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out.
473 | if (IA[str.charAt(i)] < 0)
474 | sepCnt++;
475 |
476 | // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045.
477 | if ((sLen - sepCnt) % 4 != 0)
478 | return null;
479 |
480 | // Count '=' at end
481 | int pad = 0;
482 | for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;)
483 | if (str.charAt(i) == '=')
484 | pad++;
485 |
486 | int len = ((sLen - sepCnt) * 6 >> 3) - pad;
487 |
488 | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
489 |
490 | for (int s = 0, d = 0; d < len;) {
491 | // Assemble three bytes into an int from four "valid" characters.
492 | int i = 0;
493 | for (int j = 0; j < 4; j++) { // j only increased if a valid char was found.
494 | int c = IA[str.charAt(s++)];
495 | if (c >= 0)
496 | i |= c << (18 - j * 6);
497 | else
498 | j--;
499 | }
500 | // Add the bytes
501 | dArr[d++] = (byte) (i >> 16);
502 | if (d < len) {
503 | dArr[d++]= (byte) (i >> 8);
504 | if (d < len)
505 | dArr[d++] = (byte) i;
506 | }
507 | }
508 | return dArr;
509 | }
510 |
511 | /** Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as
512 | * fast as {@link #decode(String)}. The preconditions are:null will throw an exception.
518 | * @return The decoded array of bytes. May be of length 0.
519 | */
520 | public final static byte[] decodeFast(String s)
521 | {
522 | // Check special case
523 | int sLen = s.length();
524 | if (sLen == 0)
525 | return new byte[0];
526 |
527 | int sIx = 0, eIx = sLen - 1; // Start and end index after trimming.
528 |
529 | // Trim illegal chars from start
530 | while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0)
531 | sIx++;
532 |
533 | // Trim illegal chars from end
534 | while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0)
535 | eIx--;
536 |
537 | // get the padding count (=) (0, 1 or 2)
538 | int pad = s.charAt(eIx) == '=' ? (s.charAt(eIx - 1) == '=' ? 2 : 1) : 0; // Count '=' at end.
539 | int cCnt = eIx - sIx + 1; // Content count including possible separators
540 | int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0;
541 |
542 | int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes
543 | byte[] dArr = new byte[len]; // Preallocate byte[] of exact length
544 |
545 | // Decode all but the last 0 - 2 bytes.
546 | int d = 0;
547 | for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) {
548 | // Assemble three bytes into an int from four "valid" characters.
549 | int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s.charAt(sIx++)];
550 |
551 | // Add the bytes
552 | dArr[d++] = (byte) (i >> 16);
553 | dArr[d++] = (byte) (i >> 8);
554 | dArr[d++] = (byte) i;
555 |
556 | // If line separator, jump over it.
557 | if (sepCnt > 0 && ++cc == 19) {
558 | sIx += 2;
559 | cc = 0;
560 | }
561 | }
562 |
563 | if (d < len) {
564 | // Decode last 1-3 bytes (incl '=') into 1-3 bytes
565 | int i = 0;
566 | for (int j = 0; sIx <= eIx - pad; j++)
567 | i |= IA[s.charAt(sIx++)] << (18 - j * 6);
568 |
569 | for (int r = 16; d < len; r -= 8)
570 | dArr[d++] = (byte) (i >> r);
571 | }
572 |
573 | return dArr;
574 | }
575 | }
576 |
--------------------------------------------------------------------------------