2017-06-16 70 views
0

我有一個問題,並嘗試解決它關於夫妻日,真的需要你的幫助。從objective-c到swift base64和hmacsha1

我需要連接到API並獲得與簽名參數 例如POST請求

URL = yourapi.com//mobile/register?client_id=3tme3bnmepmibhvv1toq4xfed&device_id=866faaa06aa1b139D&phone= 79653502956&signature=1WVoLPXcqJVKaxSK50ArFHtKtnM= 

原始數據

data ="3tme3bnmepmibhvv1toq4xfed866faaa06aa1b13979653502956" 
key = "0gkp7n6tnwdn816kyzfp26s3e" 

的主要問題是在簽名。它需要這樣的

Java示例中產生

signature = Base64.encode(HMAC_SHA1.digest(data, Base64.decode(client_secret))) 

我有一個與Base64和hamcsha1(CommonCrypto)

#import "Base64.h" 

@interface Base64() 

@end 

@implementation Base64 

static const char _base64EncodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 
static const short _base64DecodingTable[256] = { 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63, 
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2, 
    -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2, 
    -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 
}; 

+ (NSString *) encodeString: (NSString *) strData { 
    return [self encodeData: [strData dataUsingEncoding: NSUTF8StringEncoding] ]; 
} 

+ (NSString *) encodeData: (NSData *) objData { 
    const unsigned char * objRawData = [objData bytes]; 
    char * objPointer; 
    char * strResult; 

    // Get the Raw Data length and ensure we actually have data 
    unsigned long intLength = [objData length]; 
    if (intLength == 0) return nil; 

    // Setup the String-based Result placeholder and pointer within that placeholder 
    strResult = (char *)calloc(((intLength + 2)/3) * 4, sizeof(char)); 
    objPointer = strResult; 

    // Iterate through everything 
    while (intLength > 2) { // keep going until we have less than 24 bits 
     *objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; 
     *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; 
     *objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)]; 
     *objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f]; 

     // we just handled 3 octets (24 bits) of data 
     objRawData += 3; 
     intLength -= 3; 
    } 

    // now deal with the tail end of things 
    if (intLength != 0) { 
     *objPointer++ = _base64EncodingTable[objRawData[0] >> 2]; 
     if (intLength > 1) { 
      *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)]; 
      *objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2]; 
      *objPointer++ = '='; 
     } else { 
      *objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4]; 
      *objPointer++ = '='; 
      *objPointer++ = '='; 
     } 
    } 

    // Terminate the string-based result 
    *objPointer = '\0'; 

    // Return the results as an NSString object 
    NSString *result = @(strResult); 

    free(strResult); 

    return result; 
} 

+ (NSData *) decodeString: (NSString *) strBase64 { 
    const char * objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding]; 
    unsigned long intLength = strlen(objPointer); 
    int intCurrent; 
    int i = 0, j = 0, k; 

    unsigned char * objResult; 
    objResult = calloc(intLength, sizeof(unsigned char)); 

    // Run through the whole string, converting as we go 
    while (((intCurrent = *objPointer++) != '\0') && (intLength-- > 0)) { 
     if (intCurrent == '=') { 
      if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) { 
       // the padding character is invalid at this point -- so this entire string is invalid 
       free(objResult); 
       return nil; 
      } 
      continue; 
     } 

     intCurrent = _base64DecodingTable[intCurrent]; 
     if (intCurrent == -1) { 
      // we're at a whitespace -- simply skip over 
      continue; 
     } else if (intCurrent == -2) { 
      // we're at an invalid character 
      free(objResult); 
      return nil; 
     } 

     switch (i % 4) { 
      case 0: 
       objResult[j] = intCurrent << 2; 
       break; 

      case 1: 
       objResult[j++] |= intCurrent >> 4; 
       objResult[j] = (intCurrent & 0x0f) << 4; 
       break; 

      case 2: 
       objResult[j++] |= intCurrent >>2; 
       objResult[j] = (intCurrent & 0x03) << 6; 
       break; 

      case 3: 
       objResult[j++] |= intCurrent; 
       break; 
     } 
     i++; 
    } 

    // mop things up if we ended on a boundary 
    k = j; 
    if (intCurrent == '=') { 
     switch (i % 4) { 
      case 1: 
       // Invalid state 
       free(objResult); 
       return nil; 

      case 2: 
       k++; 
       // flow through 
      case 3: 
       objResult[k] = 0; 
     } 
    } 

    // Cleanup and setup the return NSData 
    NSData * objData = [[NSData alloc] initWithBytes:objResult length:j] ; 
    free(objResult); 
    return objData; 

} 

@end 

的Objective-C在其餘客戶

工作的老Objective-C代碼
+ (NSString*)signParametersWithString:(NSString*)parameters 
          withSecret:(NSString*)clientSecret 
{ 
    // Base64 Decode. 
    NSData* keyData = [Base64 decodeString:clientSecret]; 
    NSString *strData = [[NSString alloc]initWithData:keyData encoding:NSUTF8StringEncoding]; 

    // DO NOT USE !!! [[NSData alloc] initWithBase64EncodedString:clientSecret options:0]; 

    const char* cData = [parameters cStringUsingEncoding:NSASCIIStringEncoding]; 

    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH]; 

    // Sign with HMAC SHA1. 
    CCHmac(kCCHmacAlgSHA1, [keyData bytes], [keyData length], cData, strlen(cData), cHMAC); 

    NSData* HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)]; 

    // Base64 Encode. 
    NSLog(@"%@", HMAC); 
    return [HMAC base64EncodedStringWithOptions:0]; 

} 

我試圖使用StackOverflow社區在swift上工作,但它不是w工作會有。

斯威夫特代碼

 let data = Data("3tme3bnmepmibhvv1toq4xfed866faaa06aa1b13979653502956".utf8) 
     let key = Data("0gkp7n6tnwdn816kyzfp26s3e".utf8).base64EncodedString() 
     let hmac = data.hmacsha1(key: key) 

extension Data { 

    func hmacsha1(key: String) -> String? { 
     guard let keyData = Data(base64Encoded: key) else { 
      return nil 
     } 
     var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) 
     self.withUnsafeBytes({ dataBytes in 
      keyData.withUnsafeBytes({ keyDataBytes in 
       CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), keyDataBytes, keyData.count, dataBytes, self.count, &digest) 
      }) 
     }) 
     return Data(bytes: digest).base64EncodedString() 
    } 
} 

而且它的產生。

signature = "pd6oB8P8Yq92gn7eYH0qAnSLFbI=" 

但我需要這個

signature = "1WVoLPXcqJVKaxSK50ArFHtKtnM=" 

我需要幫助解決迅速FUNC或如何使OBJ-C代碼斯威夫特項目。我認爲這在解碼base64時存在錯誤,但我現在不知道如何弄清楚。

+1

通常的方法將是同時運行Objective-C和銀行代碼一步一步,並比較中間結果(稱爲「調試」)。 Swift代碼在哪一步產生與Objective-C代碼不同的值? –

+0

當一個密鑰正在解碼 –

回答

0

問題解決

let keyData: NSData = Base64.decode(secret_key) as NSData 
     let cData = param_signature 


     let hmacResult: String = cData.hmac(algorithm: HMACAlgorithm.SHA1, key: keyData) 


enum HMACAlgorithm { 
    case MD5, SHA1, SHA224, SHA256, SHA384, SHA512 

    func toCCHmacAlgorithm() -> CCHmacAlgorithm { 
     var result: Int = 0 
     switch self { 
     case .MD5: 
      result = kCCHmacAlgMD5 
     case .SHA1: 
      result = kCCHmacAlgSHA1 
     case .SHA224: 
      result = kCCHmacAlgSHA224 
     case .SHA256: 
      result = kCCHmacAlgSHA256 
     case .SHA384: 
      result = kCCHmacAlgSHA384 
     case .SHA512: 
      result = kCCHmacAlgSHA512 
     } 
     return CCHmacAlgorithm(result) 
    } 

    func digestLength() -> Int { 
     var result: CInt = 0 
     switch self { 
     case .MD5: 
      result = CC_MD5_DIGEST_LENGTH 
     case .SHA1: 
      result = CC_SHA1_DIGEST_LENGTH 
     case .SHA224: 
      result = CC_SHA224_DIGEST_LENGTH 
     case .SHA256: 
      result = CC_SHA256_DIGEST_LENGTH 
     case .SHA384: 
      result = CC_SHA384_DIGEST_LENGTH 
     case .SHA512: 
      result = CC_SHA512_DIGEST_LENGTH 
     } 
     return Int(result) 
    } 
} 

extension String { 
    func hmac(algorithm: HMACAlgorithm, key: NSData) -> String { 
     let cKey = key 
     let cData = self.cString(using: String.Encoding.ascii) 
     var cHMAC = [CC_SHA1_DIGEST_LENGTH] 
     CCHmac(algorithm.toCCHmacAlgorithm(), cKey.bytes, cKey.length, cData, Int(strlen(cData!)), &cHMAC) 
     let hmacData:NSData = NSData(bytes: cHMAC, length: (Int(algorithm.digestLength()))) 
     let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) 
     return String(hmacBase64) 
    } 
}