3 Replies
      Latest reply on Aug 7, 2015 1:45 AM by eskimo
      Tim9909 Level 1 Level 1 (5 points)

        I am trying to generate an RSA key pair and retrieve the key bytes on OSX.  I tried using the technique illustrated by the CryptoExercise sample code for iOS.  Everything seems to work, except I always get back only 96 bytes when I try to retrieve the key bytes, regardless of the key size.  Here is the code I am using:

         

          CFMutableDictionaryRef query;

          query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

          CFDictionarySetValue(query,kSecClass,kSecClassKey);

          CFDictionarySetValue(query,kSecAttrKeyType,kSecAttrKeyTypeRSA);

          CFDictionarySetValue(query,kSecAttrApplicationTag,publicTag);

          CFDictionarySetValue(query,kSecReturnData,kCFBooleanTrue);

          CFDictionarySetValue(query,kSecReturnAttributes,kCFBooleanTrue);

          CFDictionaryRef attr;

          status = SecItemCopyMatching(query, (CFTypeRef *)&attr);

         

        The dictionary attributes show the correct property for the key, but the "v_Data" has only 96 bytes.  Likewise, if I omit the kSecReturnAttributes and just request kSecReturnData.  The same code works correctly on iOS, returning the key length + 12 bytes (DER format).

         

        Any trick to make this work on OSX?  I guess I can use OpenSSL, which I need anyway for Linux server side.  But I was hoping to have iOS compatible code running on OSX for development.

        • Re: SecItemCopyMatching() not able to retrieve public key data on OS X
          eskimo Apple Staff Apple Staff (12,095 points)

          On OS X you must export the key using one of the keychain export APIs.  For example:

          - (NSData *)subjectPublicKeyInfoDataForPublicKey:(SecKeyRef)publicKey {
              BOOL                success;
              NSData *            result;
              CFDataRef          exportResult;
          
              result = nil;
          
              success = SecItemExport(publicKey, kSecFormatOpenSSL, 0, NULL, &exportResult) == errSecSuccess;
              if (success) {
                  result = CFBridgingRelease(exportResult);
              }
          
              return result;
          }
          

          Share and Enjoy

          Quinn "The Eskimo!"
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: SecItemCopyMatching() not able to retrieve public key data on OS X
              Tim9909 Level 1 Level 1 (5 points)

              Thanks, that worked, though I'm afraid I may end up using OpenSSL.  Ideally, I wanted to have same code running on Linux + OSX + iOS, or at worst only 2 variants.  Also, I had wanted to generate keys with exponent=3, to push more of the work load from encrypt to decrypt side, but it looks like SecKeyGeneratePair() always uses 65537.  It would be nice to see asymmetric crypto included in the common crypto library for applications that just want the algorithms not keychain integration.

                • Re: SecItemCopyMatching() not able to retrieve public key data on OS X
                  eskimo Apple Staff Apple Staff (12,095 points)

                  It would be nice to see asymmetric crypto included in the common crypto library for applications that just want the algorithms not keychain integration.

                  The best way to get that feedback in front of folks who have the power to effect change is to file an enhancement request for it.  Please post your bug number, just for the record.

                  Also, I had wanted to generate keys with exponent=3, to push more of the work load from encrypt to decrypt side, but it looks like SecKeyGeneratePair() always uses 65537.

                  Ditto.

                  Share and Enjoy

                  Quinn "The Eskimo!"
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"