LoginSignup
7
9

More than 5 years have passed since last update.

SecKeyRawSign and SecKeyRawVerify in Swift

Last updated at Posted at 2015-11-12

SecKeyRawSign and SecKeyRawVerify in Swift

RSAの公開鍵/秘密鍵を作成した前回のエントリーの後に署名に挑戦しました.その実装も複雑で時間がかかったため公開します.

Crypto.swift

Crypto.swift
import Foundation
import CoreFoundation
import Security

class Crypto {
    func test() {
        let string: String = "sample text to be encrypted and decrypted"
        let keyPair: (publicKey: SecKey?, privateKey: SecKey?) = generateKeyPair()
        let signature: NSData? = signString(string, privateKey: keyPair.privateKey!)
        let result: Bool = verifyString(string, signature: signature!, publicKey: keyPair.publicKey!)
        print(result)
    }

    func generateKeyPair () -> (publicKey: SecKey?, privateKey: SecKey?) {
        let parameters: [String: AnyObject] = [
            kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
            kSecAttrKeySizeInBits as String: 2048
        ]
        var publicKey: SecKey?
        var privateKey: SecKey?
        let osStatus: OSStatus = SecKeyGeneratePair(parameters, &publicKey, &privateKey)
        switch osStatus {
        case noErr:
            return (publicKey, privateKey)
        default:
            return (nil, nil)
        }
    }

    func signString(string: String, privateKey: SecKey) -> NSData? {
        let digest = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))!
        let stringData: NSData = string.dataUsingEncoding(NSUTF8StringEncoding)!
        CC_SHA256(stringData.bytes, CC_LONG(stringData.length), UnsafeMutablePointer<UInt8>(digest.mutableBytes))
        let signedData: NSMutableData = NSMutableData(length: SecKeyGetBlockSize(privateKey))!
        var signedDataLength: Int = signedData.length

        let err: OSStatus = SecKeyRawSign(
            privateKey,
            SecPadding.PKCS1SHA256,
            UnsafePointer<UInt8>(digest.bytes),
            digest.length,
            UnsafeMutablePointer<UInt8>(signedData.mutableBytes),
            &signedDataLength
        )

        switch err {
        case noErr:
            return signedData
        default:
            return nil
        }

    }

    func verifyString(string: String, signature: NSData, publicKey: SecKey) -> Bool {
        let digest = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))!
        let stringData: NSData = string.dataUsingEncoding(NSUTF8StringEncoding)!
        CC_SHA256(stringData.bytes, CC_LONG(stringData.length), UnsafeMutablePointer<UInt8>(digest.mutableBytes))

        let err: OSStatus = SecKeyRawVerify(
            publicKey,
            SecPadding.PKCS1SHA256,
            UnsafePointer<UInt8>(digest.bytes),
            digest.length,
            UnsafeMutablePointer<UInt8>(signature.bytes),
            signature.length
        )

        switch err {
        case noErr:
            return true
        default:
            return false
        }
    }
}

使い方

Objective-Cのライブラリを利用しているため,Playgroundでは動きません.

Brigding Header内でCommonCryptoをインポートしてください.

Crypto-Bridging-Header.h
#import <CommonCrypto/CommonCrypto.h>
7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9