繁体   English   中英

从Objective-C到Swift Base64和Hmacsha1

[英]From objective-c to swift base64 and hmacsha1

我有一个问题,尝试在几天内解决,确实需要您的帮助。

我需要连接到API并获得带有签名参数示例的发布请求

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)一起使用的旧的Objective-C代码

#import "Base64.h"

@interface Base64()

@end

@implementation Base64

static const char _base64EncodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
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

+ (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代码

        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="

我需要帮助来修复Swift函数或如何使obj-c代码在Swift项目中工作。 我认为那是解码base64的错,但是我现在不知道如何解决。

问题解决了

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)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM