Files
keyboard/Shared/KBSignUtils.m
CodeST 5edf1751ff 修改sign。
键盘里ai回复的bug
2026-02-24 14:59:06 +08:00

172 lines
5.8 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// KBSignUtils.m
// keyBoard
//
// Created by Mac on 2025/12/4.
//
#import "KBSignUtils.h"
#import <CommonCrypto/CommonCrypto.h>
@implementation KBSignUtils
static NSString *const KBSignAppId = @"loveKeyboard";
static NSString *const KBSignSecret = @"kZJM39HYvhxwbJkG1fmquQRVkQiLAh2H";
static NSString *KBSignStringFromObject(id obj) {
if (!obj || obj == (id)kCFNull) {
return nil;
}
if ([obj isKindOfClass:[NSString class]]) {
return (NSString *)obj;
}
if ([obj isKindOfClass:[NSNumber class]]) {
return [(NSNumber *)obj stringValue];
}
if ([obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSDictionary class]]) {
NSJSONWritingOptions options = 0;
if (@available(iOS 11.0, *)) {
options = NSJSONWritingSortedKeys;
}
NSData *data = [NSJSONSerialization dataWithJSONObject:obj options:options error:nil];
if (data.length > 0) {
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
return [obj description];
}
+ (NSString *)urlEncode:(NSString *)value {
if (!value) return @"";
// 按 application/x-www-form-urlencoded 规则编码(更贴近后端常见实现)
NSMutableCharacterSet *allowed = [NSMutableCharacterSet alphanumericCharacterSet];
[allowed addCharactersInString:@"-._*"];
NSString *encoded = [value stringByAddingPercentEncodingWithAllowedCharacters:allowed];
if (!encoded) {
return value;
}
// 空格改为 +URLEncoder 风格)
encoded = [encoded stringByReplacingOccurrencesOfString:@"%20" withString:@"+"];
return encoded;
}
+ (NSString *)hmacSHA256:(NSString *)data secret:(NSString *)secret {
const char *cKey = [secret cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256,
cKey,
strlen(cKey),
cData,
strlen(cData),
cHMAC);
// 转十六进制小写字符串
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", cHMAC[i]];
}
return output;
}
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
secret:(NSString *)secret {
NSString *dataString = [self signSourceStringWithParams:params secret:secret];
return [self hmacSHA256:dataString secret:secret];
}
+ (NSString *)signSourceStringWithParams:(NSDictionary<NSString *, NSString *> *)params
secret:(NSString *)secret {
// 1. 过滤空值 & sign 自身
NSMutableDictionary<NSString *, NSString *> *filtered = [NSMutableDictionary dictionary];
[params enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
if (!obj || obj.length == 0) return;
if ([[key lowercaseString] isEqualToString:@"sign"]) return;
filtered[key] = obj;
}];
// 2. 按 key 字典序排序
NSArray<NSString *> *sortedKeys = [[filtered allKeys] sortedArrayUsingSelector:@selector(compare:)];
// 3. 拼接 key=value&key2=value2...&secret=xxx
NSMutableArray<NSString *> *components = [NSMutableArray array];
for (NSString *key in sortedKeys) {
NSString *value = filtered[key] ?: @"";
NSString *encodedValue = [self urlEncode:value];
NSString *part = [NSString stringWithFormat:@"%@=%@", key, encodedValue];
[components addObject:part];
}
NSString *encodedSecret = [self urlEncode:secret ?: @""];
NSString *secretPart = [NSString stringWithFormat:@"secret=%@", encodedSecret];
[components addObject:secretPart];
return [components componentsJoinedByString:@"&"];
}
+ (NSString *)currentTimestamp {
NSTimeInterval ts = [[NSDate date] timeIntervalSince1970];
long long seconds = (long long)ts;
return [NSString stringWithFormat:@"%lld", seconds];
}
+ (NSString *)generateNonceWithLength:(NSUInteger)length {
// 用 UUID 生成,去掉 - , 再截取前 length 位
NSString *uuid = [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""];
if (length == 0 || length > uuid.length) {
return uuid;
}
return [uuid substringToIndex:length];
}
+ (NSDictionary<NSString *, NSString *> *)signHeadersWithBodyParams:(NSDictionary *)bodyParams {
NSString *timestamp = [self currentTimestamp];
NSString *nonce = [self generateNonceWithLength:16];
NSMutableDictionary<NSString *, NSString *> *signParams = [NSMutableDictionary dictionary];
if (KBSignAppId.length > 0) {
signParams[@"appId"] = KBSignAppId;
}
if (timestamp.length > 0) {
signParams[@"timestamp"] = timestamp;
}
if (nonce.length > 0) {
signParams[@"nonce"] = nonce;
}
if ([bodyParams isKindOfClass:[NSDictionary class]] && bodyParams.count > 0) {
[bodyParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if (![key isKindOfClass:[NSString class]]) {
return;
}
NSString *value = KBSignStringFromObject(obj);
if (value.length == 0) {
return;
}
signParams[(NSString *)key] = value;
}];
}
NSString *sign = [self signWithParams:signParams secret:KBSignSecret ?: @""];
NSMutableDictionary<NSString *, NSString *> *headers = [NSMutableDictionary dictionary];
if (sign.length > 0) {
headers[@"X-Sign"] = sign;
}
if (KBSignAppId.length > 0) {
headers[@"X-App-Id"] = KBSignAppId;
}
if (timestamp.length > 0) {
headers[@"X-Timestamp"] = timestamp;
}
if (nonce.length > 0) {
headers[@"X-Nonce"] = nonce;
}
return [headers copy];
}
@end