RSA-SHA1 signing with a PKCS#12 private key
// | |
// RSASHA1.swift | |
// | |
// Copyright (c) 2015 Neil Cowburn. All rights reserved. | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
// THE SOFTWARE. | |
// | |
import Security | |
public typealias RSASigningResult = (signedData: NSData?, error: NSError?) | |
public func rsa_sha1(data plainData: NSData, #privateKey: SecKey!) -> RSASigningResult { | |
var digest = NSMutableData(length: Int(CC_SHA1_DIGEST_LENGTH))! | |
// Hash the data | |
CC_SHA1(plainData.bytes, CC_LONG(plainData.length), UnsafeMutablePointer<UInt8>(digest.mutableBytes)) | |
// Then sign it | |
var signedData = NSMutableData(length: SecKeyGetBlockSize(privateKey))! | |
var signedDataLength = signedData.length | |
let err: OSStatus = SecKeyRawSign(privateKey, | |
SecPadding(kSecPaddingPKCS1SHA1), | |
UnsafePointer<UInt8>(digest.bytes), | |
digest.length, | |
UnsafeMutablePointer<UInt8>(signedData.mutableBytes), | |
&signedDataLength) | |
if err == errSecSuccess { | |
return (signedData: signedData, error: nil) | |
} | |
return (signedData: nil, error: NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil)) | |
} | |
public func PKCS12ReadKey(path keyFilePath: String, #password: String?) -> SecKey? { | |
let p12KeyFileContent = NSData(contentsOfFile: keyFilePath, options: .DataReadingMappedAlways, error: nil) | |
if (p12KeyFileContent == nil) { | |
NSLog("Cannot read PKCS12 file from \(keyFilePath)") | |
return nil | |
} | |
let options = [String(kSecImportExportPassphrase.takeUnretainedValue()):password ?? ""] | |
var citems: Unmanaged<CFArray>? = nil | |
let resultPKCS12Import = withUnsafeMutablePointer(&citems) { citemsPtr in | |
SecPKCS12Import(p12KeyFileContent, options, citemsPtr) | |
} | |
if (resultPKCS12Import != errSecSuccess) { | |
return nil | |
} | |
let items = citems!.takeRetainedValue() as NSArray | |
let myIdentityAndTrust = items.objectAtIndex(0) as! NSDictionary | |
let identityKey = String(kSecImportItemIdentity.takeUnretainedValue()) | |
let identity = myIdentityAndTrust[identityKey] as! SecIdentity | |
let trustKey = String(kSecImportItemTrust.takeUnretainedValue()) | |
let trust = myIdentityAndTrust[trustKey] as! SecTrust | |
// MARK - Private Key | |
var privateKey: Unmanaged<SecKey>? = nil | |
let resultCopyPrivateKey = withUnsafeMutablePointer(&privateKey) { | |
privateKeyPtr in | |
SecIdentityCopyPrivateKey(identity, privateKeyPtr) | |
} | |
if (resultCopyPrivateKey != errSecSuccess) { | |
NSLog("SecIdentityCopyPrivateKey fail") | |
return nil | |
} | |
return privateKey!.takeRetainedValue() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment