32728
■現状  
クライアント側の担当でC#コードを組んでいます。  
API通信時にPHP側とハッシュが一致しないので  
PHP側のソースを解析して同じものを作っているつもりなのですが、  
出力される結果が一致しません。

■質問  
PHP側とC#側でSha512のハッシュ作成時に注意すべき事やC#側のコード上問題のある点を  
指摘していただけないでしょうか？

サーバーから支持のあったハッシュ値での導通テストは上手くいけたので  
クライアント側の作成しているハッシュ値に問題がありそうです。

下記サイトでPHPのソースを実行してみたのですがサーバー側と同じになりました。  
<https://www.codechef.com/ide>

■PHP側

```

    $strdata = hash('sha512', base64_decode(トークン文字列) . １６桁文字列);
    print_r($strdata);
    
```

■C#側

```

    Encoding enc = Encoding.GetEncoding("UTF-8");
    string decode =
        enc.GetString(Convert.FromBase64String(トークン文字列));
    
    string decode_result = decode + １６桁文字列;
    
    byte[] result;
    SHA512 shaM = new SHA512Managed();
    result = shaM.ComputeHash(System.Text.Encoding.UTF8.GetBytes(decode_result));
    
    string hash = System.Text.Encoding.UTF8.GetString(result);
    
```

■環境  
Unity5.5.1p1  
C#3.0  
.net2.0

以上、よろしくお願いします。
CC BY-SA 3.0
2017-02-16T08:13:34.020
32716
2017-02-16T13:34:42.053
5261
question
php c#
php側のSha512のハッシュとC#側のSha512のハッシュが一致しません
>
```

>     string hash = System.Text.Encoding.UTF8.GetString(result);
>  
```

ではなく

```

    string hash = BitConverter.ToString(result);
    
```

でどうでしょうか？
CC BY-SA 3.0
2017-02-16T08:19:01.037
32717
2017-02-16T08:19:01.037
4236
32716
answer
* 本来のSHA256ハッシュは、バイナリーの任意のバイト列から固定長のバイト列を生成します。

  * PHPの`hash`関数は、入力文字列を単なるバイト列とみなしてハッシュ値(上記のバイト列)を生成し、その各バイトを2桁の16進に変換した文字列を返します。  
(オプションによりハッシュ値のバイト列をそのまま返すようにもできますが、コード例ではそうしていません。今回はサーバサイドのコードはそのまま、と言う前提のようなので上記を前提に考えます。)

※従って、「１６桁文字列」の中身と、サーバ側PHPの内部文字列コードの設定によっては結果が変わってきます。ここでは『「１６桁文字列」の中身はASCII文字のみ』または『サーバ側PHPの内部文字列コードの設定はUTF-8』と仮定しておきます。

  * 入力となる「トークン」が、「何らかのバイト列」をbase-64エンコードしたものであることは、PHPのコードから仮定できると思いますが、その「何らかのバイト列」がUTF-8の文字列として解釈できるかどうかはわかりません。ここでは『「何らかのバイト列」が文字列として解釈できるかどうかは不明』と仮定しておきます。

と言うわけで上記の前提・仮定に基づいて、C#側で同じ動作をするコードを書くと、こんな感じになります。

```

    using System;
    using System.Text;
    using System.Security.Cryptography;
    using System.Linq;
    
    //...
    
    Encoding utf8 = Encoding.UTF8;
    //トークン文字列(token)をbase-64で変換したバイト配列をそのまま使う
    byte[] decoded_bytes = Convert.FromBase64String(token);
    //１６桁文字列(str16)もバイト列に変換して、バイト列として結合する
    byte[] decoded_result = decoded_bytes.Concat(utf8.GetBytes(str16)).ToArray();
    
    SHA512 shaM = new SHA512Managed();
    byte[] result = shaM.ComputeHash(decoded_result);
    
    //ハッシュ値のバイト列を16進表現に変換する
    string hash = System.BitConverter.ToString(result).Replace("-", "");
    Console.WriteLine(hash);
    
```

こちらで確認した範囲では、PHPのコードと同じ結果(16進表現の大文字・小文字が異なる)を返します。お試しください。
CC BY-SA 3.0
2017-02-16T13:34:42.053
32728
2017-02-16T13:34:42.053
13972
32716
answer