Ios集成支付宝,网上已经有很多方法,响应的demo也有。也就不啰嗦了。最后因为是支付,所以使用了RSA(非对称加密密钥的一种)。demo中没用加密,主要是密钥签名,这样做的作用就是防止订单在传输工程中数据有没有被改。和我们最早做的串口传输协议中CRC校验是一个目的。
支付宝给的demo是基于OPENSLL库的,这是一个功能强大权威,但庞大又很丑,尤其对于我们爱好object C或者习惯了面向对象的语言的程序员来说,很不希望自己的工程内有这么个怪物。所以我决定用其他的库代替openssl进行支付宝的RSA签名。
在做这之前,淘宝的开发水平真不怎么让人敬仰。等到网上搜了一下,还真没有好的库,唯一的只有apple自己谢的一个《Objective-C-RSA-maste》例子中的SecKeyWrapper类,其他的人都是模仿此例子做的。然而很多时候都和支付宝签名不通。
首先我们看看ios自己的安全加密的库有哪些:
库 |
功能 |
支持平台 |
使用方法 |
Security Transform API |
1. 签名 sign 2. 验证verify 3. base64 编码解码 |
仅支持Mac |
SecItemImport导入密钥做成secKeyref。只支持pem格式。 |
Common Cypoto |
1. 只支持对称密钥 2. 只能加密解码 |
Mac和IOS |
1. 通过pkcs12import导入p12格式的证书,从中提取SecKeyref。 2. 手工拼凑SecKeyref |
CDSA/CSSA 已经废弃 |
|
|
|
还有一些证书,密钥已经PKCS8术语需要整理,我以前只知道个有对称不对称CA什么的,这次被这些概念头疼了2天,才大概有一个概念:
名称 |
格式 |
内容特征 |
用途 |
文件 |
|
RSA 密钥 |
文本 |
明文PKCS#1 |
-----BEGIN RSA PRIVATE KEY----- BASE64 ENCODED DATA -----END RSA PRIVATE KEY----- |
非JAVA |
*.pem *.cer部分 |
加密 DES-EDE3-CBC或BASE64或MD5算法生成key |
-----BEGINENCRYPTED PRIVATE KEY---- BASE64 ENCODED DATA -----ENDENCRYPTED PRIVATE KEY----- |
非JAVA |
*.key *.pem *.cer部分 |
||
PKCS8 |
-----BEGIN PRIVATE KEY---- BASE64私钥内容 -----END PRIVATEKEY----- |
||||
PKCS8 加密 |
-----BEGIN ENCRYPTED PRIVATE KEY— BASE64私钥内容 -----ENDENCRYPTED PRIVATE KEY----- |
||||
二进制
|
都加密(用DES) |
JAVA |
*.der *.cer |
||
RSA公钥 |
文本PKCS#1 |
-----BEGIN RSA PUBLIC KEY----- BASE64 ENCODED DATA -----END RSA PUBLIC KEY----- |
|
|
|
PKCS8 |
-----BEGIN PUBLIC KEY----- BASE64 ENCODED DATA -----END PUBLIC KEY----- |
||||
二进制 |
|
|
Der Cer |
||
PKCS12 |
加密的证书 |
证书内包括 |
|
*p12 *.pfx |
密钥+签= 证书
源代码改写了前辈们写的RSA类文件。中间有包私密钥加密,私密钥解密等,这些都是使用手动增加密钥串。密钥字符串带有\n换行。如下:
NSString *pubkey = @"-----BEGIN PUBLICKEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLuwt30JLYFvKcFOUdjPuDRdqv\nSnDb5TSdA/w0ND/GwLExpT66DeRz9+6//G//Y0y3c/yWT14k/ab1vID4U6W3vOgr\nafC0RyuIgH8ooCTNQpU+LtIoZ6qCejnux7VZ5lwWeT/9DQjWOtf6TopeRdzmOX09\nwa7c5xGGUsmi29QxDQIDAQAB\n-----ENDPUBLIC KEY-----";
注意支付宝下还是用PKCS8格式的密钥。
类在Objective-C-RSA-master这个例子上进行了更改。
增加了以下两个签名函数:
+ (NSString *)signString:(NSString *)stringwithPrivatekey:(NSString *)privKey;
+ (NSString *)signString:(NSString *)stringbyP12File:(NSString*)fileName password:(NSString*)pwd_string;
一个是用导入p12格式的证书。如下例子
//************************************************** NSString** p12filename = @"yourp12filname";//不加后缀
NSString* p12pwd_string = @"890000";
NSString *signedString2 = [RSA signString:orderSpecbyP12File:p12filename password:p12pwd_string];
//**************************************************
签名完成按照支付宝的demo‘例子调用即可。
//**************************************************
NSString*signedString = [RSA signString:orderSpecwithPrivatekey:privateKey_formatstring ];
NSLog(@"signedString using RSA = %@",signedString );
//将签名成功字符串格式化为订单字符串,请严格按照该格式
NSString*orderString = nil;
if(signedString != nil) {
orderString= [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString,@"RSA"];
NSLog(@"orderString = %@",orderString);
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appSchemecallback:^(NSDictionary *resultDic) {
NSLog(@"reslut = %@",resultDic);
}];
}
[tableView deselectRowAtIndexPath:indexPathanimated:YES];
还有第二个更简单,使用格式化好的含有PKCS8格式的密钥字符串调用。
//*******************************************************************************
NSString*signedString = [RSA signString:orderSpec withPr
ivatekey:privateKey_formatstring ];
这样可以用返回的签名串按照上面支付。
本来使用这个方法进行签名返回串,刚开始发现一直连不通,查看支付宝的例子发现他多进行网络的URL转码,一时也没查清楚为什么把BASE64转换成UrlEncode,将此函数加入后成功连接支付宝服务器。交易完成。将更改后的RAH类文件在附件内,希望能改大家方便。这里上传不了附件,就附在下面:
源代码:RSA.h
#import <Foundation/Foundation.h>
#define kChosenCipherBlockSize kCCBlockSizeAES128
#define kChosenCipherKeySize kCCKeySizeAES128
#define kChosenDigestLength CC_SHA1_DIGEST_LENGTH
// Global constants for padding schemes.
#define kPKCS111
#define kTypeOfSigPadding kSecPaddingPKCS1SHA1
@interface RSA : NSObject
// return base64 encoded string
+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
// return raw data
+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;
// return base64 encoded string
// enc with private key NOT working YET!
//+ (NSString