HttpGet request to the Binance exchange error with java - java

I have a trouble with send HTTP Get request via Binance exchange.
(I need to return my wallet status)
the GitHub manual says that (https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md)
Account information (USER_DATA)
GET /api/v3/account (HMAC SHA256)
Get current account information.
Weight: 5
Parameters:
Name Type Mandatory Description
recvWindow LONG NO
timestamp LONG YES
my codes are as shown follows
public static String timestamp = String.valueOf(System.currentTimeMillis());
public static void wallet_status () throws NoSuchAlgorithmException, InvalidKeyException {
String url = "https://api.binance.com/api/v3/account&timestamp=" + timestamp;
//sign url
Mac shaMac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(BINANCE_SECRET_KEY.getBytes(), "HmacSHA256");
shaMac.init(keySpec);
final byte[] macData = shaMac.doFinal(url.getBytes());
String sign = Hex.encodeHexString(macData);
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet("https://api.binance.com/api/v3/account"+"?timestamp="+timestamp+"?signature="+sign);
request.addHeader("X-MBX-APIKEY", BINANCE_API_KEY);
try {
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
try (InputStream stream = entity.getContent()) {
BufferedReader reader =
new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
} //end
the server response is like below
{"code":-1100,"msg":"Illegal characters found in parameter 'timestamp'; legal range is '^[0-9]{1,20}$'."}
but my String timestamp is a 13 digit numeric string which should be no problem. please help.

Your url is wrong. Change ?signature= to &signature=.
You have to use & as the delimeter for subsequent variables in a URL. Currently, the ?signature... is seen as the value of the timestamp variable, causing that error message.

Query string delimiter is & not ?
Use: "https://api.binance.com/api/v3/account"+"?timestamp="+timestamp+"&signature="+sign

This Post is really old, but maybe someone will help this solution:
// Binance testnet Data
private String baseUrl = "https://api.binance.com";
private String apiKey = "you API Key";
private String apiSecret = "Your Secret";
private String endpoint = "/api/v3/account";
private String parameters = "recvWindow=20000&timestamp=" + System.currentTimeMillis();
public void getData() throws Exception {
byte[] bytes = hmac("HmacSHA256", apiSecret.getBytes(), parameters.getBytes());
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(baseUrl + endpoint + "?" + parameters + "&signature=" + bytesToHex(bytes)))
.setHeader("X-MBX-APIKEY", apiKey)
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response.statusCode());
// print response body
System.out.println(response.body());
}
public static byte[] hmac(String algorithm, byte[] key, byte[] message) throws Exception {
Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(message);
}
public static String bytesToHex(byte[] bytes) {
final char[] hexArray = "0123456789abcdef".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for (int j = 0, v; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}

Related

Microsoft graph search feature Java

I'm trying to use Microsoft Graph to make a file search. I use this entry point : https://graph.microsoft.com/beta/search/query
My application do not use a user account but a daemon with an application key (see auth method).
And i send a built object.
My java code is rather simple :
public static void main(String[] args) throws Exception{
try {
// Authentication result containing token
IAuthenticationResult result = getAccessTokenByClientCredentialGrant();
String token = result.accessToken();
SearchDocumentResponseModel documentQuery = fileGraphs.searchDocument(token, QUERYSTRING, 0, 25);
System.out.println("Find a document" + documentQuery.toString());
} catch(Exception ex){
throw ex;
}
}
private static IAuthenticationResult getAccessTokenByClientCredentialGrant() throws Exception {
ConfidentialClientApplication app = ConfidentialClientApplication.builder(
CONFIDENTIAL_CLIENT_ID,
ClientCredentialFactory.createFromSecret(CONFIDENTIAL_CLIENT_SECRET))
.authority(TENANT_SPECIFIC_AUTHORITY)
.build();
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
Collections.singleton(GRAPH_DEFAULT_SCOPE))
.build();
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
return future.get();
}
The SearchDocumentResponseModel is just a set of POJO that build for me the object that i must send as a request body.
{
"requests":
[{
"entityTypes":["microsoft.graph.driveItem"],
"query":{"query_string":{"query":"any query"}},
"from":0,"size":25
}]
}
The method searchDocument is just here to build the object before i send it to the API
public SearchDocumentResponseModel searchDocument(String accessToken, String stringSearch, int from, int size) throws IOException {
SearchDocumentRequestModel searchRequest = new SearchDocumentRequestModel();
// set values here
...
URL url = new URL("https://graph.microsoft.com/beta/search/query");
return requestsBuilder.buildPostRequest(accessToken, searchRequest, url)
}
Now i want to send to server the Json and expect an answer :
public SearchDocumentResponseModel buildPostRequest(String accessToken, SearchDocumentRequestModel searchRequest, URL url) throws IOException {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
conn.setRequestProperty("Accept","application/json");
conn.setRequestProperty("Content-Type","application/json; utf-8");
conn.setDoOutput(true);
conn.setRequestMethod("POST");
// write the input json in a string
String jsonInputString = new Gson().toJson(searchRequest);
try(OutputStream os = conn.getOutputStream()) {
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
int httpResponseCode = conn.getResponseCode();
String httpResponseMessage = conn.getResponseMessage();
// reading the response
try(BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
String outputResponse = response.toString();
return new Gson().fromJson(outputResponse, SearchDocumentResponseModel.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I think i set the properties correctly. Is it coming from my code or from Microsoft Graph ? Thanks !
First of all, you should check if the access token is valid, you can send a request using postman.
If the token is valid, I think it should be the problem of your jsonInputString. The following code works fine.
URL url = new URL("https://graph.microsoft.com/beta/search/query");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "access_token" );
conn.setRequestProperty("Accept","application/json");
conn.setRequestProperty("Content-Type","application/json; utf-8");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
String str = "";
str += "{";
str += " \"requests\": [";
str += " {";
str += " \"entityTypes\": [";
str += " \"microsoft.graph.driveItem\"";
str += " ],";
str += " \"query\": {";
str += " \"query_string\": {";
str += " \"query\": \"contoso\"";
str += " }";
str += " },";
str += " \"from\": 0,";
str += " \"size\": 25";
str += " }";
str += " ]";
str += "}";
OutputStream os = conn.getOutputStream();
byte[] input = str.getBytes("UTF-8");
os.write(input, 0, input.length);
System.out.println(conn.getResponseCode());
Update:
Query api doesn't support client credential flow.

Generating cookie from website that implements testcookie-nginx-module

This is a follow question on this answer: Link Here
Based on that answer I am able to bypass the security check of testcookie-nginx-module used by byethost hosting.
The problem is that the cookies I used are copied from a web browser. I need to get the COOKIE from my website, using my android device so that I can use it to make request on byethost server.
Byethost provides a __test cookie to check for validity of a request on an existing session, if it seems that the only way for me to access to server is to be a "valid browser", How to tell the server that I am valid browser from an android device? So that I can have the cookie given to the web browsers.
I met the same problem and first I used WebView to access the page and get the cookies, use that to bypass the security check of testcookie-nginx-module
WebView myWebView = new WebView(this);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl("my_page_here");
String cookies = CookieManager.getInstance().getCookie("my_page_here");
System.out.println(cookies);
myWebView.destroy();
Then to use with Volley, i created a CustomRequest extends StringRequest and override getHeaders like this:
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240 ");
params.put("Cookie", cookies+"; expires=Fri, 1-Jan-38 06:55:55 GMT; path=/");
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
And that's all, do you have any other solution yet? if not you could check this :D
In case someone still needs a better answer, I would like to add mine.
First, I created a Splash Screen Activity which first connects to the byethost server and get the response and then parse the "__test" cookie from it.
void getCookie() {
RequestQueue mQueue = Volley.newRequestQueue(this);
StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.SERVER_URL,
response -> {
try {
if (response.contains("src=\"/aes.js\"") || response.contains("src=\"/aes.min.js\"")) {
String beginOffsetA = "var a=toNumbers(\"";
String beginOffsetB = "\"),b=toNumbers(\"";
String beginOffsetC = "\"),c=toNumbers(\"";
String endOffsetC = "\");document.cookie=";
String a = response.substring((response.indexOf(beginOffsetA) + (beginOffsetA).length()), response.indexOf(beginOffsetB)); // Value of var a
String b = response.substring((response.indexOf(beginOffsetB) + (beginOffsetB).length()), response.indexOf(beginOffsetC)); // Value of var b
String c = response.substring((response.indexOf(beginOffsetC) + (beginOffsetC).length()), response.indexOf(endOffsetC)); // Value of var c
Constants.COOKIE = "__test=" + encrypt(hexStringToByteArray(a), hexStringToByteArray(b), hexStringToByteArray(c)).toLowerCase() + "; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; //This is the "__test" Cookie, e.g., "__test=8927389y1huwieqyue"
} else {
theServerDoesNotNeedTestCookie();
}
} catch (Exception e){
e.printStackTrace();
didntWork();
}
},
error -> doesNotWork();
);
mQueue.add(stringRequest);
}
public String encrypt(byte[] key, byte[] initVector, byte[] data) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
byte[] encrypted = cipher.doFinal(data);
return bytesToHex(encrypted);
} catch (Exception ex) {
new Reporter(this, ex);
}
return null;
}
public String bytesToHex(byte[] bytes) {
final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
This works for byethost.

Sending request from Java to Box for uploading files

I want to upload file to Box using Java HTTP RESTFUL requests.
My code is,
File file = new File("C:/Users/Developer/Desktop/cloud.ppt");
Base64.Encoder encoder = Base64.getEncoder();
Base64.Decoder decoder = Base64.getDecoder();
String boundary1 = "----------------------------741e90d31eff";
String header1 = "--"+boundary1+"\nContent-Disposition: form-data; name=\"file\"; filename="+file.getName()+";\nContent-Type: application/octet-stream";
System.out.println("=====header1======="+header1);
String footer1 = "--"+boundary1+"--";
String header2= header1;
header1 = header1+"\r\n\r\n";
byte[] byteConvert = header1.getBytes("UTF-8");
String headerEncoded1 = encoder.encodeToString(byteConvert);
HttpResponse response;
System.out.println("******headerEncoded1*****"+headerEncoded1);
byte[] byteConvert2 = header2.getBytes("UTF-8");
while(headerEncoded1.endsWith("="))
{
header2+=' ';
header2 = header2+"\r\n\r\n";
byteConvert2 = header2.getBytes("UTF-8");
headerEncoded1 = encoder.encodeToString(byteConvert2);
}
byte fileContent[] = new byte[(int)file.length()];
System.out.println("fileContent[]: " +fileContent);
FileInputStream fin = new FileInputStream(file);
fin.read(fileContent);
fin.close();
String fileContentString = new String(fileContent);
String fileBody = fileContentString;
byteConvert2 = fileBody.getBytes("UTF-8");
System.out.println("byteConvert2: " +byteConvert2);
String bodyEncoded1 = encoder.encodeToString(byteConvert2);
System.out.println("***bodyEncoded1***"+bodyEncoded1);
String bodyBlob = null;
String last4Bytes = bodyEncoded1.substring(bodyEncoded1.length()-4,bodyEncoded1.length());
System.out.println("****last4Bytes****"+last4Bytes);
if(last4Bytes.endsWith("=="))
{
System.out.println("=== if ===");
last4Bytes = last4Bytes.substring(0,2) + "0K";
bodyEncoded1 = bodyEncoded1.substring(0,bodyEncoded1.length()-4) + last4Bytes;
byteConvert2 = footer1.getBytes("UTF-8");;
String footerEncoded = encoder.encodeToString(byteConvert2);
String Combine = headerEncoded1+bodyEncoded1+footerEncoded;
byteConvert2 = Combine.getBytes("UTF-8");
byte[] byteConvert3 = decoder.decode(byteConvert2);
bodyBlob = byteConvert3.toString();
System.out.println("\n***if bodyBlob***"+bodyBlob);
}
else if(last4Bytes.endsWith("="))
{
System.out.println("===else if bodyBlob===");
last4Bytes = last4Bytes.substring(0,3) + "N";
bodyEncoded1 = bodyEncoded1.substring(0,bodyEncoded1.length()-4) + last4Bytes;
footer1 = "\n" + footer1;
byteConvert2 = footer1.getBytes("UTF-8");
String footerEncoded = encoder.encodeToString(byteConvert2);
String strCombineNew= headerEncoded1+bodyEncoded1+footerEncoded;
byteConvert2 = strCombineNew.getBytes("UTF-8");
byte[] byteConvert3 = decoder.decode(byteConvert2);
bodyBlob = byteConvert3.toString();
System.out.println("\n****else if bodyBlob***"+bodyBlob);
}
else
{
System.out.println("===else===");
footer1 = "\r\n" + footer1;
byteConvert2 = footer1.getBytes("UTF-8");
String footerEncoded = encoder.encodeToString(byteConvert2);
String strCombine = headerEncoded1+bodyEncoded1+footerEncoded;
byteConvert2 = strCombine.getBytes("UTF-8");
byte[] byteConvert3 = decoder.decode(byteConvert2);
bodyBlob = byteConvert3.toString();
System.out.println("\n***else***"+bodyBlob);
}
//System.out.println("****bodyBlob***"+bodyBlob);
//java.sql.Blob blob = org.hibernate.Hibernate.createBlob(bodyBlob.getBytes());
//System.out.println("=====blob======"+blob);
String strFolderId = "XXXXXXX";
HttpClient httpclient = HttpClientBuilder.create().build();
String sUrl = "https://upload.box.com/api/2.0/files/content?parent_id="+strFolderId;
HttpPost request = new HttpPost(sUrl);
request.setEntity(new StringEntity(bodyBlob));
request.setHeader("Content-Type","multipart/form-data; boundary="+boundary1);
request.setHeader("Authorization", "Bearer" +strAccessTokenOnly);
System.out.println("\n=== Content-Length ===" +String.valueOf(fileBody.length()));
request.setHeader("Content-Length",String.valueOf(fileBody.length()));
response = httpclient.execute(request);
System.out.println("\n=== response ==="+response.getStatusLine());
Here, If I set header with Content-Length, the execution will stop in between.
And If I did not add the setHeader I am getting as Bad Request, Status 400.
If anyone have worked on related to this scenario, please help me..
Thanks in advance

Encrypting Joda Date combined with username as a single variable

I am working in a Spring-MVC application and for password reset function, i am sending an email, which contains the username+Joda Date. Before sending it, I would like to encrypt the content(date+username) in such a way that they can be perfectly reversed. As far as my theoretical understanding goes, doesn't reversing defeat the purpose of encryption in first place? If not, then I would like to encrypt them and then some mechanism to decrypt them. There are some solutions I found, one of them mentions retrieving but I cannot figure out which entity is which. I am pasting the code below. Kindly have a look :
Encryption and decryption :
byte[] userBytes = username.getBytes("UTF-8");
byte[] keyBytes = key.getBytes("UTF-8");
//XOR scramble
byte[] encrypted = new byte[userBytes.length];
for(int i = 0; i < userBytes.length; i++){
encrypted[i] = (byte)(userBytes[i] ^ keyBytes[i % keyBytes.length]);
}
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(encrypted);
// webappB, decode the parameter
BASE64Decoder decoder = new BASE64Decoder();
byte[] decoded = decoder.decodeBuffer( encoded );
//XOR descramble
byte[] decrypted = new byte[decoded.length];
for(int i = 0; i < decoded.length; i++){
decrypted[i] = (byte)(decoded[i] ^ keyBytes[i % keyBytes.length] );
}
This class has two public methods, one for generating token and another for validating it. It is abridged from much larger and more complex code, so, some errors might be introduced. There are also some tests embedded, so you can play with it immediately. Any way, I hope it will be sufficient to get you on the right track.
package tokens;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class TokenUtils {
private static final String HMAC_ALGO = "HmacSHA256";
private static final String TOKEN_SEPARATOR = ":";
private static final long MAX_AGE = 1_000 * 60 * 60 * 24; // 24h
private TokenUtils() {
}
public static String createToken(String username, long timestamp, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
StringBuilder sb = new StringBuilder();
sb.append(generateTokenStringPublicPart(username, timestamp));
sb.append(TOKEN_SEPARATOR);
sb.append(computeSignature(username, timestamp, secretKey));
return sb.toString();
}
public static boolean verifyToken(String token, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
String[] parts = token.split(TOKEN_SEPARATOR);
boolean result = false;
if (parts.length == 3) {
String username = parts[0];
Long timestamp = Long.valueOf(parts[1]);
String signature = parts[2];
if (signature.equals(computeSignature(username, timestamp, secretKey))) {
if (System.currentTimeMillis() - timestamp < MAX_AGE) {
result = true;
}
}
}
return result;
}
private static String generateTokenStringPublicPart(String username, long timestamp) {
StringBuilder sb = new StringBuilder();
sb.append(username);
sb.append(TOKEN_SEPARATOR);
sb.append(timestamp);
return sb.toString();
}
private static String computeSignature(String username, long timestamp, String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {
StringBuilder sb = new StringBuilder();
sb.append(generateTokenStringPublicPart(username, timestamp));
SecretKeySpec sks = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), HMAC_ALGO);
Mac hmac = Mac.getInstance(HMAC_ALGO);
hmac.init(sks);
return Base64.getUrlEncoder().encodeToString(hmac.doFinal(sb.toString().getBytes(StandardCharsets.UTF_8)));
}
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
String secretKey = "secret_key";
String token = TokenUtils.createToken("marko", System.currentTimeMillis(), secretKey);
System.out.println(token);
System.out.println("Original token verification: " + TokenUtils.verifyToken(token, secretKey));
token = token.replaceAll("a", "b");
System.out.println("Tampered token verification: " + TokenUtils.verifyToken(token, secretKey));
token = TokenUtils.createToken("marko", System.currentTimeMillis() - 1_000 * 60 * 60 * 48, secretKey);
System.out.println("Expired token verification: " + TokenUtils.verifyToken(token, secretKey));
}
}

Java SHA512 digest output differs from PHP script

Can someone figure out why the output of these (php and java) snippets of code don't return the same SHA512 for the same input?
$password = 'whateverpassword';
$salt = 'ieerskzcjy20ec8wkgsk4cc8kuwgs8g';
$salted = $password.'{'.$salt.'}';
$digest = hash('sha512', $salted, true);
echo "digest: ".base64_encode($digest);
for ($i = 1; $i < 5000; $i++) {
$digest = hash('sha512', $digest.$salted, true);
}
$encoded_pass = base64_encode($digest);
echo $encoded_pass;
This is the code on the android application:
public String processSHA512(String pw, String salt, int rounds)
{
try {
md = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("No Such Algorithm");
}
String result = hashPw(pw, salt, rounds);
System.out.println(result);
return result;
}
private static String hashPw(String pw, String salt, int rounds) {
byte[] bSalt;
byte[] bPw;
String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString();
try {
bSalt = appendedSalt.getBytes("ISO-8859-1");
bPw = pw.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Unsupported Encoding", e);
}
byte[] digest = run(bPw, bSalt);
Log.d(LCAT, "first hash: " + Base64.encodeBytes(digest));
for (int i = 1; i < rounds; i++) {
digest = run(digest, bSalt);
}
return Base64.encodeBytes(digest);
}
private static byte[] run(byte[] input, byte[] salt) {
md.update(input);
return md.digest(salt);
}
The library for base64 encoding is this: base64lib
This java code is actually some modified code I found around another question in StackOverflow.
Although the Android code is running fine it doesn't match with the output from the php script. It doesn't even match the first hash!
Note 1: On php hash('sha512',$input, $raw_output) returns raw binary output
Note 2: On java I tried to change the charset (UTF-8, ASCII) but it also didn't work.
Note 3: The code from the server can not be changed, so I would appreciate any answer regarding how to change my android code.
The first hash should be the same on the server and in Java. But then in the loop what gets appended to the digest is password{salt} in the PHP code, but only {salt} in the Java code.
For the lazy ones, one example better than a thousand words ;). I finally understood what was happening. The method update appends bytes to the digest, so when you append $password.{$salt} is the same as doing mda.update(password bytes) and the mda.digest("{$salt}" bytes. I do that answer because I was going crazy finding why it was not working and it was all in this answer.
Thanks guys.
This is the example that works in a Java Server:
public static String hashPassword(String password, String salt) throws Exception {
String result = password;
String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString();
String appendedSalt2 = new StringBuilder().append(password).append('{').append(salt).append('}').toString();
if(password != null) {
//Security.addProvider(new BouncyCastleProvider());
MessageDigest mda = MessageDigest.getInstance("SHA-512");
byte[] pwdBytes = password.getBytes("UTF-8");
byte[] saltBytes = appendedSalt.getBytes("UTF-8");
byte[] saltBytes2 = appendedSalt2.getBytes("UTF-8");
byte[] digesta = encode(mda, pwdBytes, saltBytes);
//result = new String(digesta);
System.out.println("first hash: " + new String(Base64.encode(digesta),"UTF-8"));
for (int i = 1; i < ROUNDS; i++) {
digesta = encode(mda, digesta, saltBytes2);
}
System.out.println("last hash: " + new String(Base64.encode(digesta),"UTF-8"));
result = new String(Base64.encode(digesta));
}
return result;
}
private static byte[] encode(MessageDigest mda, byte[] pwdBytes,
byte[] saltBytes) {
mda.update(pwdBytes);
byte [] digesta = mda.digest(saltBytes);
return digesta;
}

Categories