title: Matching Base64 encoded HMAC-SHA1 strings in iOS/Objective-c Ruby/Rails
body: <p>I know there are a lot of posts about converting NSData to NSString, NSData to Base64 encoded string, generating HMAC etc. but none that seem to answer how to generate matching Base64 encoded HMAC-SHA1 strings in iOS and Rails.</p>
  
  <p>Using the code below, the signatures do not match. </p>
  
  <p>iOS code:</p>
  
  <pre><code>NSString *secret = @"xxx";
  NSString *data = @"http://someurl?someparams";
  const char *cKey = [secret cStringUsingEncoding:NSASCIIStringEncoding];
  const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
  unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
  CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
  NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
  NSString *signature = [HMAC base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
  </code></pre>
  
  <p>Rails code:</p>
  
  <pre><code>secret = "xxx";
  data = "http://someurl?someparams";
  hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret.encode("ASCII"), data.encode("ASCII"))
  signature = Base64.encode64(hmac)
  puts "HMAC #{hmac}"
  puts "Signature #{signature}"
  </code></pre>
  
  <p>iOS output:</p>
  
  <pre><code>HMAC &lt;05651433 c9a3d449 5816ded7 80bef87f dc903e4a&gt; 
  Signature BWUUM8mj1ElYFt7XgL74f9yQPko=
  </code></pre>
  
  <p>Rails output:</p>
  
  <pre><code>HMAC 05651433c9a3d4495816ded780bef87fdc903e4a
  Signature MDU2NTE0MzNjOWEzZDQ0OTU4MTZkZWQ3ODBiZWY4N2ZkYzkwM2U0YQ==
  </code></pre>
  
  <p>Using following code I can get them to match. But it feels hacky (use of description and string replacements in iOS side and <code>chomp</code> in Rails):</p>
  
  <p>iOS code:</p>
  
  <pre><code>NSString *secret = @"xxx";
  NSString *data = @"http://someurl?someparams";
  const char *cKey = [secret cStringUsingEncoding:NSASCIIStringEncoding];
  const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
  unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
  CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
  NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
  NSString *HMACStr = [[HMAC description] stringByReplacingOccurrencesOfString:@"&lt;" withString:@""];
  HMACStr = [HMACStr stringByReplacingOccurrencesOfString:@"&gt;" withString:@""];
  HMACStr = [HMACStr stringByReplacingOccurrencesOfString:@" " withString:@""];
  HMAC = [HMACStr dataUsingEncoding:NSASCIIStringEncoding];
  NSString *signature = [HMAC base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
  NSLog(@"HMAC %@", [HMAC description]);
  NSLog(@"Signature %@", signature);
  </code></pre>
  
  <p>Rails code:</p>
  
  <pre><code>secret = "xxx"
  data = "http://someurl?someparams"
  hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), secret.encode("ASCII"), data.encode("ASCII"))
  signature = Base64.encode64(hmac).chomp
  puts "HMAC #{hmac}"
  puts "Signature #{signature}"
  </code></pre>
  
  <p>iOS output:</p>
  
  <pre><code>HMAC &lt;30353635 31343333 63396133 64343439 35383136 64656437 38306265 66383766 64633930 33653461&gt; 
  Signature MDU2NTE0MzNjOWEzZDQ0OTU4MTZkZWQ3ODBiZWY4N2ZkYzkwM2U0YQ== 
  </code></pre>
  
  <p>Rails output:</p>
  
  <pre><code>HMAC 05651433c9a3d4495816ded780bef87fdc903e4a
  Signature MDU2NTE0MzNjOWEzZDQ0OTU4MTZkZWQ3ODBiZWY4N2ZkYzkwM2U0YQ==
  </code></pre>
  
  <p>How can I generate matching signatures without using the hacks?</p>