SecPKCS12Import
이라는 기능이있어 p12 파일에서 데이터를 가져올 수 있습니다. 그러나 나는 반대 방향으로 가고 싶다. 나는 SecCertificateRef
과 공공/전용 SecKeyRef
을 가지고 있는데, P12 파일을 만드는데 사용하고 싶습니다. 누구든지 iPhone에서이 작업을 수행하는 방법을 알고 있습니까?P12 파일 Xcode를 생성 하시겠습니까?
감사
SecPKCS12Import
이라는 기능이있어 p12 파일에서 데이터를 가져올 수 있습니다. 그러나 나는 반대 방향으로 가고 싶다. 나는 SecCertificateRef
과 공공/전용 SecKeyRef
을 가지고 있는데, P12 파일을 만드는데 사용하고 싶습니다. 누구든지 iPhone에서이 작업을 수행하는 방법을 알고 있습니까?P12 파일 Xcode를 생성 하시겠습니까?
감사
불행하게도, CommonCrypto은 (는 OSX의 대응이 그렇게 할 수 있지만) PKCS12 컨테이너 혼자 다른 내보내기 기능을하게 내보낼 수있는 수단이 제공하지 않습니다. 키 체인에서 SecKeyRef 원시 데이터를 추출하는 방법이 있지만 그 다음에는 모든 PKCS12를 직접 작성해야합니다.
비슷한 문제가 발생하여 OpenSSL을 사용했습니다. 당신이 컴파일하고 OpenSSL이 자신을 소싱 연결 필요로하는 아이폰 OS OpenSSL을 통합
을 위해 OpenSSL을 컴파일
는 약간의 작업이 필요합니다. 다행히도 빌드 스크립트가 있으므로 사용할 필요가 없습니다 (예 : https://github.com/x2on/OpenSSL-for-iPhone). 약간의 개암 (hazel) 인 Makefile을 패치해야 할 때 사용하는 것이 좋습니다. 이러한 빌드 스크립트는 iOS와 tvOS 모두를위한 정적 링크 라이브러리를 생성합니다. 프로젝트에 링크를 연결하고 그에 따라 헤더 및 라이브러리 검색 경로를 설정하면됩니다.
CocoaPods
또한 공식 OpenSSL CocoaPod 사용할 수 있습니다. 따라서 프로젝트를 구성하는 번거 로움을 줄일 수 있습니다.
당신이 알고 있겠지만 PKCS12
내보내기에는 OpenSSL은 C library이다. 즉, 모든 C 함수를 Objective-C 또는 Swift 래퍼로 캡슐화 할 수 있습니다. PKCS12 컨테이너를 가져 오거나 내보낼 수있는 오픈 소스 래퍼가 있지만 좋은 설명서가있는 단일 컨테이너를 찾지 못했습니다. 일부 소스에서 관련 스 니펫을 유도 할 수 있어야합니다.
https://github.com/microsec/MscX509Common/blob/master/src/MscPKCS12.m
이 예뿐만 아니라 http://fm4dd.com/openssl/pkcs12test.htm을 볼 수있다.
희망 하시겠습니까?
이 작업은 OpenSSL을 통해서만 수행 할 수 있다는 것에 동의합니다. iOS 용으로 컴파일하는 것은 약간 까다 롭지 만, OpenSSL-for-iPhone을 사용하는 것은 가능합니다.
는SecCertificate
에서
PKCS12 키 스토어 및 프로젝트에
스위프트 3 단지 추가 정적 라이브러리
libssl.a
와
SecKey
및
libcrypto.a
을 만드는 주어진 과제를 해결하고 다음 브리지 헤더를 만들려면 :
#import <openssl/err.h>
#import <openssl/pem.h>
#import <openssl/pkcs12.h>
#import <openssl/x509.h>
을
키 스토어를 만들려면 입력 데이터를 OpenSSL 데이터 구조로 변환해야하며 이는 약간의 창의성을 필요로합니다.SecCertificate
은 DER 형식으로 직접 변환 한 다음 X509 구조로 읽을 수 있습니다. SecKey
은 처리하기가 훨씬 더 어렵습니다. 키의 데이터를 얻는 유일한 방법은 키 체인에 데이터를 쓰고 참조를 얻는 것입니다. 참조에서 기본 64 인코딩 된 문자열을 가져올 수 있으며이 문자열은 EVP_PKEY
구조로 읽을 수 있습니다. 이제 키 스토어를 만들어 파일에 저장할 수 있습니다. 아이폰 OS 기능을 통해 키 스토어의 데이터에 액세스하기 위해 우리는 전체 솔루션은 다음과 같다 let data = FileManager.default.contents(atPath: path)! as NSData
를 통해 파일을 읽을 수 있어야합니다
func createP12(secCertificate: SecCertificate, secPrivateKey: SecKey) {
// Read certificate
// Convert sec certificate to DER certificate
let derCertificate = SecCertificateCopyData(secCertificate)
// Create strange pointer to read DER certificate with OpenSSL
// data must be a two-dimensional array containing the pointer to the DER certificate as single element at position [0][0]
let certificatePointer = CFDataGetBytePtr(derCertificate)
let certificateLength = CFDataGetLength(derCertificate)
let certificateData = UnsafeMutablePointer<UnsafePointer<UInt8>?>.allocate(capacity: 1)
certificateData.pointee = certificatePointer
// Read DER certificate
let certificate = d2i_X509(nil, certificateData, certificateLength)
// Print certificate
X509_print_fp(stdout, certificate)
// Read private key
// Convert sec key to PEM key
let tempTag = "bundle.temp"
let tempAttributes = [
kSecClass: kSecClassKey,
kSecAttrApplicationTag: tempTag,
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecValueRef: secPrivateKey,
kSecReturnData: kCFBooleanTrue
] as NSDictionary
var privateKeyRef: AnyObject?
// Store private key in keychain
SecItemDelete(tempAttributes)
guard SecItemAdd(tempAttributes, &privateKeyRef) == noErr else {
NSLog("Cannot store private key")
return
}
// Get private key data
guard let privateKeyData = privateKeyRef as? Data else {
NSLog("Cannot get private key data")
return
}
let pemPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\n\(privateKeyData.base64EncodedString())\n-----END RSA PRIVATE KEY-----\n"
// Delete private key in keychain
SecItemDelete(tempAttributes)
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)
// !!! Remove in production: Print private key
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()
}
을 또한, 나는이에 대한 인증서와 개인 키를 보내려면 서버, OpenSSL 라이브러리를 사용하지 않고 다른 방법으로 그것을 할 수 있습니까? – hockeybro
이론적으로 비공개 및 공개 키는 키 체인에서 NSData로 내보낼 수 있지만 직접 구현해야하는 PEM, DER, X.509 또는 PKCS12와 같은 추가 형식을 내보낼 수 있습니다. 불행히도, 우리는이 앱에서 결코 작동하지 않습니다. 관심이 있으시면'SecItemCopyMatching'을보세요. 행운을 빕니다! –
OpenSSL에서 PKCS12를 생성하고 전체 라이브러리를 가져 오는 대신이 코드를 복사하는 코드 스 니펫을 얻을 수 있습니까? – hockeybro