0

I´m trying to encode a String in SHA256. I know how the output should look like. This I´ve got from a working Java:

string = "1234nonce=1234"

SHA256 Hash from string in Java:

string.digest() =
[-29, -80, -60, 66, -104, -4, 28, 20, -102, -5, -12, -56, -103, 111,
-71, 36, 39, -82, 65, -28, 100, -101, -109, 76, -92, -107, -103, 27,
120, 82, -72, 85]

Now I need to get the same result in Swift:

 func sha256() {
        let string = "1234nonce=1234"
        let intArray = [UInt8](string.utf8)
        let data = Data(bytes: intArray)

        var hash = [UInt8](repeating: 0,  count: Int(CC_SHA256_DIGEST_LENGTH))
        data.withUnsafeBytes {
            _ = CC_SHA256($0, CC_LONG(data.count), &hash)
        }
        print(hash)
        return Data(bytes: hash)
 }

But the result looks like this:

[218, 207, 142, 73, 87, 235, 210, 73, 201, 67, 19, 33, 57, 146, 69, 48, 51, 56, 0, 212, 172, 114, 118, 31, 102, 19, 175, 51, 153, 230, 143, 67]

How the first result is generated in Java, you can see here in the last answer. (There, nonce + data corrsponds to "1234nonce=1234") I´m wondering if there is something I´m doing fundamentally wrong. Any kind of help is much appreciated.

Josch Hazard
  • 323
  • 3
  • 20

1 Answers1

2

Short answer

It seems your SHA-256 hash algorithm implementation done in the Swift language is correct.

Long answer

The Java example you are referring to does not just contain the SHA-256 hash algorithm implementation, but also contains the HMAC-SHA-512 algorithm implementation to calculate the signature (?).

All in all, if there is a need of the SHA-256 algorithm only, please check the following draft Java implementation:

package com.thecompany.test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

class Program {
    public static void main(final String[] args) throws NoSuchAlgorithmException {
        // Input.
        final String input = "1234nonce=1234";

        // Processing.
        final byte[] output = sha256(input);

        // Output.
        System.out.printf("Signed output: %s.%n", Arrays.toString(output));

        final List<Integer> unsignedOutput = unsignedIntStream(output)
            .boxed()
            .collect(Collectors.toList());
        System.out.printf("Unsigned output: %s.%n", unsignedOutput);
    }

    private static IntStream unsignedIntStream(final byte[] array) {
        return IntStream
            .range(0, array.length)
            .map(index -> Byte.toUnsignedInt(array[index]));
    }

    private static byte[] sha256(final String text) throws NoSuchAlgorithmException {
        final MessageDigest digest = MessageDigest.getInstance("SHA-256");
        return digest.digest(text.getBytes(StandardCharsets.UTF_8));
    }
}

The program produces the following output:

Signed output: [-38, -49, -114, 73, 87, -21, -46, 73, -55, 67, 19, 33, 57, -110, 69, 48, 51, 56, 0, -44, -84, 114, 118, 31, 102, 19, -81, 51, -103, -26, -113, 67].
Unsigned output: [218, 207, 142, 73, 87, 235, 210, 73, 201, 67, 19, 33, 57, 146, 69, 48, 51, 56, 0, 212, 172, 114, 118, 31, 102, 19, 175, 51, 153, 230, 143, 67].

Hope this helps.

  • Thank you, this calms me of a little bit. What I don´t understand: The author of the referred answer wrote mit all hashed output results which are leading to the final signature in the end. I tried the final signature and it worked. So on the one hand, his code is right for sure. But maybe he didn´t name it correctly. Here is what he wrote regarding the first hash: – Josch Hazard Jul 29 '17 at 23:42
  • `nonce + data = "1234nonce=1234" the SHA256 Hash from nonce + data in Java is: md.digest() = [-29, -80, -60, 66, -104, -4, 28, 20, -102, -5, -12, -56, -103, 111, -71, 36, 39, -82, 65, -28, 100, -101, -109, 76, -92, -107, -103, 27, 120, 82, -72, 85]` – Josch Hazard Jul 29 '17 at 23:43
  • Maybe he mixed it up, I don´t know, but I´m trying to go on, hopefully I´m coming to the same signature in the end. And yes, it has to become a signature and I´m trying to build all this in swift. – Josch Hazard Jul 29 '17 at 23:46
  • «And yes, it has to become a signature and I´m trying to build all this in swift.» Fine. Then it is necessary to update the Swift implementation appropriately: introduce the appropriate HMAC-SHA-512 algorithm implementation. – Sergey Vyacheslavovich Brunov Jul 29 '17 at 23:51
  • Yes, of course. [Here](https://www.kraken.com/en-us/help/api) you can see the guideline: `(URI path + SHA256(nonce + POST data))` so for `nonce + POST data` ONLY the SHA256 should be used. The HMAC-SHA-512 algorithm implementation comes after that. Still don´t understand why he comes to a different result. But I move on, hopefully I´m coming to the same signature in the end. – Josch Hazard Jul 29 '17 at 23:55
  • @JoschHazard, by the way, it looks like [objective c - Payload signature in Swift / Objc (Kraken API)](https://stackoverflow.com/questions/44879012) is a similar problem to the one you are trying to solve. Right? – Sergey Vyacheslavovich Brunov Jul 30 '17 at 00:09
  • Absolutely. But I don´t understand his approach at all. – Josch Hazard Jul 30 '17 at 00:14