Epi*_*rce 8 authentication ssl cryptography objective-c ios
这个问题显然是相似的,但没有任何答案:以编程方式为iPhone创建x509证书而不使用OpenSSL
在我们的应用程序(服务器,客户端)中,我们正在实现客户端身份验证(基于X509Certificate的SSL).我们已经有办法生成一个keypair,创建一个PKCS10 Certificate Signing Request,由此签名self-signed CA并创建一个X509Certificate,发送回来.但是,要使用SSL请求该认证,private key并X509Certificate有出口到一个PKCS12(P12) keystore.
有没有人知道如何做到这一点,或者即使它可能?客户端必须生成P12文件(我们不想发出私钥),客户端正在运行iOS,并且是移动设备.该解决方案适用于Android使用BouncyCastle(SpongyCastle),但我们没有找到任何iOS.
编辑:在Java中,此导出由以下内容完成:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
KeyStore ks = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME);
ks.load(null);
ks.setKeyEntry("key-alias", (Key) key, password.toCharArray(),
new java.security.cert.Certificate[] { x509Certificate });
ks.store(bos, password.toCharArray());
bos.close();
return bos.toByteArray();
Run Code Online (Sandbox Code Playgroud)
小智 10
如果使用openssl,则不必将完整的源代码复制到项目中,只需添加lib和头文件即可,因此可以使用openssl库而不会出现任何大小问题.您可以使用openssl生成密钥和证书:
EVP_PKEY * pkey;
pkey = EVP_PKEY_new();
RSA * rsa;
rsa = RSA_generate_key(
2048, /* number of bits for the key - 2048 is a sensible value */
RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */
NULL, /* callback - can be NULL if we aren't displaying progress */
NULL /* callback argument - not needed in this case */
);
EVP_PKEY_assign_RSA(pkey, rsa);
X509 * x509;
x509 = X509_new();
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
X509_set_pubkey(x509, pkey);
X509_NAME * name;
name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
(unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
(unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(unsigned char *)"localhost", -1, -1, 0);
X509_set_issuer_name(x509, name);
//X509_sign(x509, pkey, EVP_sha1());
const EVP_CIPHER *aConst = EVP_des_ede3_cbc();
Run Code Online (Sandbox Code Playgroud)
你可以用这些函数把它写成pem格式:
PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL);
PEM_write_X509(
f, /* write the certificate to the file we've opened */
x509 /* our certificate */
);
Run Code Online (Sandbox Code Playgroud)
之后可以将这些文件写入p12文件,源自此处:https: //github.com/luvit/openssl/blob/master/openssl/demos/pkcs12/pkwrite.c
/* pkwrite.c */
#include <stdio.h>
#include <stdlib.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
/* Simple PKCS#12 file creator */
int main(int argc, char **argv)
{
FILE *fp;
EVP_PKEY *pkey;
X509 *cert;
PKCS12 *p12;
if (argc != 5) {
fprintf(stderr, "Usage: pkwrite infile password name p12file\n");
exit(1);
}
SSLeay_add_all_algorithms();
ERR_load_crypto_strings();
if (!(fp = fopen(argv[1], "r"))) {
fprintf(stderr, "Error opening file %s\n", argv[1]);
exit(1);
}
cert = PEM_read_X509(fp, NULL, NULL, NULL);
rewind(fp);
pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
fclose(fp);
p12 = PKCS12_create(argv[2], argv[3], pkey, cert, NULL, 0,0,0,0,0);
if(!p12) {
fprintf(stderr, "Error creating PKCS#12 structure\n");
ERR_print_errors_fp(stderr);
exit(1);
}
if (!(fp = fopen(argv[4], "wb"))) {
fprintf(stderr, "Error opening file %s\n", argv[1]);
ERR_print_errors_fp(stderr);
exit(1);
}
i2d_PKCS12_fp(fp, p12);
PKCS12_free(p12);
fclose(fp);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
非常感谢你们这个很好的解决方案!
我将您的代码翻译为Swift 3并构建了以下函数,以使用签名的X509证书和RSA私钥创建P12密钥库,两者都是PEM格式:
func createP12(pemCertificate: String, pemPrivateKey: String) {
// Read certificate
let buffer = BIO_new(BIO_s_mem())
pemCertificate.data(using: .utf8)!.withUnsafeBytes({ (bytes: UnsafePointer<Int8>) -> Void in
BIO_puts(buffer, bytes)
})
let certificate = PEM_read_bio_X509(buffer, nil, nil, nil)
X509_print_fp(stdout, certificate)
// Read private key
let privateKeyBuffer = BIO_new(BIO_s_mem())
pemPrivateKey.data(using: .utf8)!.withUnsafeBytes({ (bytes: UnsafePointer<Int8>) -> Void in
BIO_puts(privateKeyBuffer, bytes)
})
let privateKey = PEM_read_bio_PrivateKey(privateKeyBuffer, nil, nil, nil)
PEM_write_PrivateKey(stdout, privateKey, nil, nil, 0, nil, nil)
// Check if private key matches certificate
guard X509_check_private_key(certificate, privateKey) == 1 else {
NSLog("Private key does not match certificate")
return
}
// Set OpenSSL parameters
OPENSSL_add_all_algorithms_noconf()
ERR_load_crypto_strings()
// Create P12 keystore
let passPhrase = UnsafeMutablePointer(mutating: ("" as NSString).utf8String)
let name = UnsafeMutablePointer(mutating: ("SSL Certificate" as NSString).utf8String)
guard let p12 = PKCS12_create(passPhrase, name, privateKey, certificate, nil, 0, 0, 0, 0, 0) else {
NSLog("Cannot create P12 keystore:")
ERR_print_errors_fp(stderr)
return
}
// Save P12 keystore
let fileManager = FileManager.default
let tempDirectory = NSTemporaryDirectory() as NSString
let path = tempDirectory.appendingPathComponent("ssl.p12")
fileManager.createFile(atPath: path, contents: nil, attributes: nil)
guard let fileHandle = FileHandle(forWritingAtPath: path) else {
NSLog("Cannot open file handle: \(path)")
return
}
let p12File = fdopen(fileHandle.fileDescriptor, "w")
i2d_PKCS12_fp(p12File, p12)
fclose(p12File)
fileHandle.closeFile()
}
Run Code Online (Sandbox Code Playgroud)
编辑:
OpenSSL可以在iOS中与OpenSSL-for-iPhone项目一起使用:
./build-libssl.sh$(YOUR_PATH)/OpenSSL-for-iPhone/include到标题搜索路径$(YOUR_PATH)/OpenSSL-for-iPhone/lib到库搜索路径libcrypto.a和libssl.a链接的框架和库项目桥接-Header.h:
#import <openssl/err.h>
#import <openssl/pem.h>
#import <openssl/pkcs12.h>
#import <openssl/x509.h>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9506 次 |
| 最近记录: |