title: Using Security Transforms to verify an RSA signature created with Ruby/OpenSSL
body: <p>I'm trying to implement a simple license key scheme for my app and I'm running into significant roadblocks. I'm following the example at <a href="http://sigpipe.macromates.com/2004/using-openssl-for-license-keys" rel="nofollow noreferrer">OpenSSL for License Keys</a>.</p>
  <p>Since that blog post was written in 2004 and OpenSSL has been deprecated on OS X I'm attempting to use the Security Transforms API to accomplish the license key verification instead of OpenSSL. I'm generating the private and public keys with OpenSSL, however; the license key is generated using the private key by a Ruby web app using the Ruby OpenSSL wrapper library from a SHA-256 digest of the purchaser's email address.</p>
  <p>The problem is that nothing I do seems to produce a signature from Ruby using OpenSSL that the Security Transforms API will verify.</p>
  <p>The Ruby code I'm working off of is:</p>
  <pre><code>require('openssl')
  
  # The email address used as the content of the license key.
  license = 'test@example.com'
  
  # Generate the public/private keypair.
  `openssl genrsa -out private_key.pem 2048`
  `openssl rsa -in conductor.pem -out public_key.data -pubout`
  
  # Get the private key and a hash of the license.
  private_key = OpenSSL::PKey::RSA.new(File.read('private_key.pem'))
  signature   = OpenSSL::Digest::SHA256.digest(license)
  
  # The signature passed to SecVerifyTransformCreate in the OS X app. I'm not sure which of these SecVerifyTransformCreate is expecting (the binary digest, a hex representation of the digest, or the original un-digested content), but none of them work.
  signature_out = signature
  #signature_out = OpenSSL::Digest::SHA256.hexdigest(license)
  #signature_out = license
  
  File.write('signature.data', signature_out)
  
  # Sign the email address to generate the license key. Using the OpenSSL::PKey::PKey#sign method produces a license key that can only be verified on the command line by running:
  #
  #   echo -n test@example.com | openssl dgst -sha256 -sign test.pem
  #
  # while using the #private_encrypt method produces a key that can only be verified on the command line by running:
  #
  #   echo -n test@example.com | openssl dgst -sha256 -binary | openssl rsautl -sign -inkey test.pem
  #
  # I'm not sure what the exact difference between the two commands above is and why they correspond to the two different Ruby signing methods below. Neither approach produces something that SecVerifyTransformCreate will verify, however.
  File.write('license_key.data',
             private_key.sign(OpenSSL::Digest::SHA256.new, license))
  #           private_key.private_encrypt(signature))
  </code></pre>
  <p>And the corresponding verification code in Objective-C:</p>
  <pre><code>// Get the data.
  NSData *publicKeyData  = [NSData dataWithContentsOfFile:@&quot;public_key.data&quot;];
  NSData *signatureData  = [NSData dataWithContentsOfFile:@&quot;signature.data&quot;];
  NSData *licenseKeyData = [NSData dataWithContentsOfFile:@&quot;license_key.data&quot;];
  
  // Import the public key.
  SecItemImportExportKeyParameters keyParameters = {};
  SecExternalFormat format = kSecFormatOpenSSL;
  SecExternalItemType type = kSecItemTypePublicKey;
  CFArrayRef publicKeys;
  
  SecItemImport((__bridge CFDataRef)publicKeyData,
                NULL,
                &amp;format,
                &amp;type,
                0,
                &amp;keyParameters,
                NULL,
                &amp;publicKeys);
  
  NSArray *publicKeysArray = (__bridge_transfer NSArray *)publicKeys;
  SecKeyRef publicKey = (__bridge SecKeyRef)publicKeysArray[0]; // TODO: How do we need to bridge this return value?
  
  CFErrorRef error = NULL;
  
  SecTransformRef verifier = SecVerifyTransformCreate(publicKey, (__bridge CFDataRef)signatureData, &amp;error);
  
  SecTransformSetAttribute(verifier, kSecTransformDebugAttributeName, kCFBooleanTrue, &amp;error);
  SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, (__bridge CFDataRef)licenseKeyData, &amp;error);
  SecTransformSetAttribute(verifier, kSecDigestTypeAttribute, kSecDigestSHA2, &amp;error);
  SecTransformSetAttribute(verifier, kSecDigestLengthAttribute, (__bridge CFNumberRef)@256, &amp;error);
  
  // I'm not sure if one of these transform attributes is necessary, but neither of them produces a verified result anyways.
  //  SecTransformSetAttribute(verifier, kSecInputIsAttributeName, kSecInputIsDigest, &amp;error);
  //  SecTransformSetAttribute(verifier, kSecInputIsAttributeName, kSecInputIsRaw, &amp;error);
  
  NSNumber *result = (__bridge NSNumber *)SecTransformExecute(verifier, &amp;error);
  
  NSLog(@&quot;Result: %@&quot;, result);
  </code></pre>
  <p>Does anyone know how I can make this work? I've literally spent days getting to the point where I'm at now and I've exhausted my ability to debug this any further, so if anyone has any insight it would be hugely appreciated!</p>