I am trying to quickly get the wrong .Net client library for the third-party service that I use to work. The source library (which works) is written in Ruby, but their equivalent library for DotNet creates different hash output for the Ruby library.
The Ruby encryption code is as follows:
def self.encrypt_string(input_string) raise Recurly::ConfigurationError.new("Recurly gem not configured") unless Recurly.private_key.present? digest_key = ::Digest::SHA1.digest(Recurly.private_key) sha1_hash = ::OpenSSL::Digest::Digest.new("sha1") ::OpenSSL::HMAC.hexdigest(sha1_hash, digest_key, input_string.to_s) end
Estimated equivalent C # code:
private static string ComputePrivateHash(string dataToProtect) { if(String.IsNullOrEmpty(Configuration.RecurlySection.Current.PrivateKey)) throw new RecurlyException("A Private Key must be configured to use the Recurly Transparent Post API."); byte[] salt_binary = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(dataToProtect)); string salt_hex = BitConverter.ToString(salt_binary).Replace("-", "").ToLower(); string salt = salt_hex.Substring(0, 20); HMACSHA1 hmac_sha1 = new HMACSHA1(Encoding.ASCII.GetBytes(Configuration.RecurlySection.Current.PrivateKey)); hmac_sha1.Initialize(); byte[] private_key_binary = Encoding.ASCII.GetBytes(salt); byte[] passkey_binary = hmac_sha1.ComputeHash(private_key_binary, 0, private_key_binary.Length); return BitConverter.ToString(passkey_binary).Replace("-", "").ToLower(); }
The actual hash output is different, however, given the same input and private key. What is wrong with the C # method, which forces it to generate incorrect hash output?
EDIT
So I would write the code, although it still produces the wrong output:
private static string ComputePrivateHash(string dataToProtect) { if(String.IsNullOrEmpty(Configuration.RecurlySection.Current.PrivateKey)) throw new RecurlyException("A Private Key must be configured to use the Recurly Transparent Post API."); var privateKey = Configuration.RecurlySection.Current.PrivateKey; var hashedData = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(dataToProtect)); var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(privateKey)); var hash = hmac.ComputeHash(hashedData); return BitConverter.ToString(hash).Replace("-", "").ToLower(); }
CORRECTED RESPONSE
Thanks to Henning's answer below, I was able to determine what the correct code is:
var privateKey = Configuration.RecurlySection.Current.PrivateKey; var hashedKey = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(privateKey)); var hmac = new HMACSHA1(hashedKey); var hash = hmac.ComputeHash(Encoding.ASCII.GetBytes(dataToProtect)); return BitConverter.ToString(hash).Replace("-", "").ToLower();