title: HMC SHA1 hash - Java producing different hash output than C#
body: <p>This is a follow up to <a href="https://stackoverflow.com/questions/7175067/hmc-sha1-hash-c-sharp-producing-different-hash-output-than-ruby">this</a> question, but I'm trying to port C# code to Java instead of Ruby code to C#, as was the case in the related question.  I am trying to verify the encrypted <a href="http://docs.recurly.com/recurlyjs/signatures" rel="nofollow noreferrer">signature</a> returned from the Recurly.js api is valid.  Unfortunately, Recurly does not have a Java library to assist with the validation, so I must implement the signature validation myself.</p>
  
  <p>Per the related question above (<a href="https://stackoverflow.com/questions/7175067/hmc-sha1-hash-c-sharp-producing-different-hash-output-than-ruby">this</a>), the following C# code can produce the hash needed to validate the signature returned from Recurly:</p>
  
  <pre><code>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();
  </code></pre>
  
  <p>Recurly provides the following example data on their <a href="http://docs.recurly.com/recurlyjs/signatures" rel="nofollow noreferrer">signature</a> documentation page:</p>
  
  <blockquote>
    <p><strong>unencrypted verification message</strong>: 
    [1312701386,transactioncreate,[account_code:ABC,amount_in_cents:5000,currency:USD]]</p>
    
    <p><strong>private key</strong>:
    0123456789ABCDEF0123456789ABCDEF</p>
    
    <p><strong>resulting signature</strong>:
    0f5630424b32402ec03800e977cd7a8b13dbd153-1312701386</p>
  </blockquote>
  
  <p>Here is my Java implementation:</p>
  
  <pre><code>String unencryptedMessage = "[1312701386,transactioncreate,[account_code:ABC,amount_in_cents:5000,currency:USD]]";
  String privateKey = "0123456789ABCDEF0123456789ABCDEF";
  String encryptedMessage = getHMACSHA1(unencryptedMessage, getSHA1(privateKey));
  
  private static byte[] getSHA1(String source) throws NoSuchAlgorithmException, UnsupportedEncodingException{
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      byte[] bytes = md.digest(source.getBytes("UTF-8"));
      return bytes;
  }
  
  private static String getHMACSHA1(String baseString, byte[] keyBytes) throws GeneralSecurityException, UnsupportedEncodingException {
      SecretKey secretKey = new SecretKeySpec(keyBytes, "HmacSHA1");
      Mac mac = Mac.getInstance("HmacSHA1");
      mac.init(secretKey);
      byte[] bytes = baseString.getBytes("ASCII");
      return Hex.encodeHexString(mac.doFinal(bytes));
  }
  </code></pre>
  
  <p>However, when I print out the encryptedMessage variable, it does not match the message portion of the example signature.  Specifically, I get a value of "c8a9188dcf85d1378976729e50f1de5093fabb78" instead of "0f5630424b32402ec03800e977cd7a8b13dbd153".</p>
  
  <p><strong>Update</strong></p>
  
  <p>Per @M.Babcock, I reran the C# code with the example data, and it returned the same output as the Java code.  So it appears my hashing approach is correct, but I am passing in the wrong data (unencryptedMessage).  Sigh. I will update this post if/when I can determine what the correct data to encrypt is- as the "unencrypted verification message" provided in the Recurly documentation appears to be missing something.</p>
  
  <p><strong>Update 2</strong></p>
  
  <p>The error turned out to be the "unencrypted verification message" data/format.  The message in the example data does not actually encrypt to the example signature provided- so perhaps outdated documentation? At any rate, I have confirmed the Java implementation will work for real-world data. Thanks to all.</p>