如何使用“US-ASCII”& amp;覆盖客户C的Java代码HmacSHA256?

时间:2015-08-11 09:31:37

标签: java ios objective-c encryption cryptography

import java.net.URLEncoder;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public static String sign(String path, String accesKeyId, Long expires, String key) throws Exception {
 String canonical = "GET\n\n\n" + expires + "\n" + path;
 byte[] keyBytes = Base64.decodeBase64(key.getBytes("US-ASCII"));
 Mac hmac = Mac.getInstance("HmacSHA256");
 hmac.init(new SecretKeySpec(keyBytes, "HmacSHA256"));
 byte[] signatureBytes = hmac.doFinal(canonical.getBytes("UTF-8"));
 String signatureBase64 = new String(Base64.encodeBase64(signatureBytes), "US-ASCII");
 String signature = URLEncoder.encode(signatureBase64, "UTF-8");
return signature;
}

输入参数:

  • 路径:/1.0/customer/abc@abc.com
  • accesKeyId:432QQYKATPUBUNHESSPDTQU
  • 到期日期:1532405086
  • key:bzjG1Z5c5 + 4on14I0zJaJFAzTs1302Ya40A6JhI2uNY =

输出应为: mWSy2mKRgG1MXeNVC1dBs6lbtx5c1lxvSy919DW5Sow%3D

请尽快告诉我。

这是我最好的尝试:

-(NSString *)getKey:(NSString*)path withAccesKeyId:(NSString*)accesKeyId withExpireTime:(long)expires withSecretKey:(NSString*)key{

    NSString *data=[NSString stringWithFormat:@"GET\n\n\n%ld\n%@",expires,path];
    NSData* bytes = [key dataUsingEncoding:NSASCIIStringEncoding];
    NSData *base64Data = [bytes base64EncodedDataWithOptions:0];
    NSData* conicalData = [data dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableData* hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, base64Data.bytes, base64Data.length, conicalData.bytes, conicalData.length, hash.mutableBytes);
    NSString *signature = [hash base64EncodedStringWithOptions:0];
    return signature;

}

我也尝试使用以下代码:

NSString *data=[NSString stringWithFormat:@"GET\n\n\n%ld\n%@",expires,path];
NSData* bytes = [key dataUsingEncoding:NSASCIIStringEncoding];
NSString *strBaseKey=[bytes base64EncodedStringWithOptions:0];;

const char *cKey  = [strBaseKey cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];

unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

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

NSString *signature = [HMAC base64EncodedStringWithOptions:0];

return signature;

**但是这两种方式都得到了这个输出**:+ CYVGnQsfZ3jHsmlo39uEHEPzGGeHlTDFbJMw5K3g8c =

1 个答案:

答案 0 :(得分:2)

你的代码很接近。

  • 第一个错误是没有正确处理Base64 key
  • 第二个错误不是对Base64字符“=”
  • 进行URL编码

这是我的例子,其中散布着原始的Java代码和NSLog语句:

NSString *path    = @"/1.0/customer/abc@abc.com";
UInt64    expires = 1532405086;
NSString *key     = @"bzjG1Z5c5+4on14I0zJaJFAzTs1302Ya40A6JhI2uNY=";
// NSString *accesKeyId = @"432QQYKATPUBUNHESSPDTQU"; // Unused

// String canonical = "GET\n\n\n" + expires + "\n" + path;
NSString *canonicalString = [NSString stringWithFormat:@"GET\n\n\n%lld\n%@", expires, path];
NSData   *canonicalData   = [canonicalString dataUsingEncoding:NSUTF8StringEncoding];
NSLog(@"canonicalData: %@", canonicalData);

// byte[] keyBytes = Base64.decodeBase64(key.getBytes("US-ASCII"));
NSData *keyData = [[NSData alloc] initWithBase64EncodedString:key options:0];
NSLog(@"keyData: %@", keyData);

// Mac hmac = Mac.getInstance("HmacSHA256");
// hmac.init(new SecretKeySpec(keyBytes, "HmacSHA256"));
// byte[] signatureBytes = hmac.doFinal(canonical.getBytes("UTF-8"));
NSMutableData *signatureData = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256,
       keyData.bytes, keyData.length,
       canonicalData.bytes, canonicalData.length,
       signatureData.mutableBytes);
NSLog(@"signatureData: %@", signatureData);

// String signatureBase64 = new String(Base64.encodeBase64(signatureBytes), "US-ASCII");
NSString *signatureBase64 = [signatureData base64EncodedStringWithOptions:0];
NSLog(@"signatureBase64: %@", signatureBase64);

// String signature = URLEncoder.encode(signatureBase64, "UTF-8");
NSCharacterSet *base64Characterset = [[NSCharacterSet characterSetWithCharactersInString:@"+/="] invertedSet];
NSString *signature = [signatureBase64 stringByAddingPercentEncodingWithAllowedCharacters:base64Characterset];
NSLog(@"signature: %@", signature);

输出:

  

canonicalData:< 4745540a 0a0a3135 33323430 35303836 0a2f312e 302f6375 73746f6d 65722f61 62634061 62632e63 6f6d>

  keyData:< 6f38c6d5 9e5ce7ee 289f5e08 d3325a24 50334ecd 77d3661a e3403a26 1236b8d6>

  signatureData:< 9964b2da 6291806d 4c5de355 0b5741b3 a95bb71e 5cd65c6f 4b2f75f4 35b94a8c>

  signatureBase64:mWSy2mKRgG1MXeNVC1dBs6lbtx5c1lxvSy919DW5Sow =
  签名:mWSy2mKRgG1MXeNVC1dBs6lbtx5c1lxvSy919DW5Sow%3D