java - 如何使用 "US-ASCII"和 HmacSHA256 将 java 代码覆盖到 Objective-C ?

标签 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
  • 键: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=

最佳答案

您的代码很接近。

  • 第一个错误是没有正确处理 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=
signature: mWSy2mKRgG1MXeNVC1dBs6lbtx5c1lxvSy919DW5Sow%3D

关于java - 如何使用 "US-ASCII"和 HmacSHA256 将 java 代码覆盖到 Objective-C ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31938150/

相关文章:

java - 这个异常例子是不是错了?

java - 如何在 JSP 中显示数据库中的图像?

swing - 自定义JCombobox默认选择背景色不可见

iOS 更新的应用程序版本 - 新的排行榜和成就

iOS App 导航

Java Date.parse IllegalArgument

ios - 如何防止调整 UIView 的大小以适应 ScrollView 的高度(禁用自动调整)?

ios 像这样滚动

iOS UIBarButtonItem Action 落到它后面的按钮

ios - 未能找到 zlib 的构建 b/c 符号