No Description

FIRInstanceIDKeyPairUtilities.m 3.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Copyright 2019 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "FIRInstanceIDKeyPairUtilities.h"
  17. #import <CommonCrypto/CommonDigest.h>
  18. #import "FIRInstanceIDKeyPair.h"
  19. #import "FIRInstanceIDLogger.h"
  20. #import "FIRInstanceIDStringEncoding.h"
  21. NSString *FIRInstanceIDWebSafeBase64(NSData *data) {
  22. // Websafe encoding with no padding.
  23. FIRInstanceIDStringEncoding *encoding =
  24. [FIRInstanceIDStringEncoding rfc4648Base64WebsafeStringEncoding];
  25. [encoding setDoPad:NO];
  26. return [encoding encode:data];
  27. }
  28. // This is NOT used for cryptographic purpose for any encryption or decryption.
  29. // This is solely to generate a random unique string for instanceID.
  30. NSData *FIRInstanceIDSHA1(NSData *data) {
  31. unsigned char output[CC_SHA1_DIGEST_LENGTH];
  32. unsigned int length = (unsigned int)[data length];
  33. CC_SHA1(data.bytes, length, output);
  34. return [NSMutableData dataWithBytes:output length:CC_SHA1_DIGEST_LENGTH];
  35. }
  36. NSDictionary *FIRInstanceIDKeyPairQuery(NSString *tag, BOOL addReturnAttr, BOOL returnData) {
  37. NSMutableDictionary *queryKey = [NSMutableDictionary dictionary];
  38. NSData *tagData = [tag dataUsingEncoding:NSUTF8StringEncoding];
  39. queryKey[(__bridge id)kSecClass] = (__bridge id)kSecClassKey;
  40. queryKey[(__bridge id)kSecAttrApplicationTag] = tagData;
  41. queryKey[(__bridge id)kSecAttrKeyType] = (__bridge id)kSecAttrKeyTypeRSA;
  42. if (addReturnAttr) {
  43. if (returnData) {
  44. queryKey[(__bridge id)kSecReturnData] = @(YES);
  45. } else {
  46. queryKey[(__bridge id)kSecReturnRef] = @(YES);
  47. }
  48. }
  49. return queryKey;
  50. }
  51. NSString *FIRInstanceIDAppIdentity(FIRInstanceIDKeyPair *keyPair) {
  52. // An Instance-ID is a 64 bit (8 byte) integer with a fixed 4-bit header of 0111 (=^ 0x7).
  53. // The variable 60 bits are obtained by truncating the SHA1 of the app-instance's public key.
  54. SecKeyRef publicKeyRef = [keyPair publicKey];
  55. if (!publicKeyRef) {
  56. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPair002,
  57. @"Unable to create a valid asymmetric crypto key");
  58. return nil;
  59. }
  60. NSData *publicKeyData = keyPair.publicKeyData;
  61. // This is used to generate a unique random string, not for encryption/decryption.
  62. NSData *publicKeySHA1 = FIRInstanceIDSHA1(publicKeyData);
  63. const uint8_t *bytes = publicKeySHA1.bytes;
  64. NSMutableData *identityData = [NSMutableData dataWithData:publicKeySHA1];
  65. uint8_t b0 = bytes[0];
  66. // Take the first byte and make the initial four 7 by initially making the initial 4 bits 0
  67. // and then adding 0x70 to it.
  68. b0 = 0x70 + (0xF & b0);
  69. // failsafe should give you back b0 itself
  70. b0 = (b0 & 0xFF);
  71. [identityData replaceBytesInRange:NSMakeRange(0, 1) withBytes:&b0];
  72. NSData *data = [identityData subdataWithRange:NSMakeRange(0, 8 * sizeof(Byte))];
  73. return FIRInstanceIDWebSafeBase64(data);
  74. }