MYKeyPair.m
changeset 3 1dfe820d7ebe
parent 2 8982b8fada63
child 4 f4709533c816
     1.1 --- a/MYKeyPair.m	Tue Apr 07 10:56:58 2009 -0700
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,246 +0,0 @@
     1.4 -//
     1.5 -//  KeyPair.m
     1.6 -//  MYCrypto
     1.7 -//
     1.8 -//  Created by Jens Alfke on 3/21/09.
     1.9 -//  Copyright 2009 Jens Alfke. All rights reserved.
    1.10 -//
    1.11 -
    1.12 -#import "MYKeyPair.h"
    1.13 -#import "MYCrypto_Private.h"
    1.14 -#import <CommonCrypto/CommonDigest.h>
    1.15 -
    1.16 -#if !MYCRYPTO_USE_IPHONE_API
    1.17 -
    1.18 -
    1.19 -#pragma mark -
    1.20 -
    1.21 -@implementation MYKeyPair
    1.22 -
    1.23 -
    1.24 -+ (MYKeyPair*) _generateRSAKeyPairOfSize: (unsigned)keySize
    1.25 -                            inKeychain: (MYKeychain*)keychain {
    1.26 -    Assert( keySize == 512 || keySize == 1024 || keySize == 2048, @"Unsupported key size %u", keySize );
    1.27 -    SecKeyRef pubKey=NULL, privKey=NULL;
    1.28 -    OSStatus err;
    1.29 -    err = SecKeyCreatePair(keychain.keychainRefOrDefault,
    1.30 -                           CSSM_ALGID_RSA, 
    1.31 -                           keySize,
    1.32 -                           0LL,
    1.33 -                           CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_VERIFY,        // public key
    1.34 -                           CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT,
    1.35 -                           CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_SIGN,          // private key
    1.36 -                           CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_PERMANENT,
    1.37 -                           NULL, // SecAccessRef
    1.38 -                           &pubKey, &privKey);
    1.39 -    if (!check(err, @"SecKeyCreatePair")) {
    1.40 -        return nil;
    1.41 -    } else
    1.42 -        return [[[self alloc] initWithPublicKeyRef: pubKey privateKeyRef: privKey] autorelease];
    1.43 -}
    1.44 -
    1.45 -
    1.46 -- (id) initWithPublicKeyRef: (SecKeyRef)publicKey privateKeyRef: (SecKeyRef)privateKey {
    1.47 -    self = [super initWithKeyRef: publicKey];
    1.48 -    if (self) {
    1.49 -        NSParameterAssert(privateKey);
    1.50 -        _privateKey = (SecKeyRef) CFRetain(privateKey);
    1.51 -    }
    1.52 -    return self;
    1.53 -}
    1.54 -
    1.55 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData
    1.56 -                   privateKey: (SecKeyRef)privateKey 
    1.57 -                  forKeychain: (SecKeychainRef)keychain {
    1.58 -    if (!privateKey) {
    1.59 -        [self release];
    1.60 -        return nil;
    1.61 -    }
    1.62 -    self = [self _initWithKeyData: pubKeyData forKeychain: keychain];
    1.63 -    if (self) {
    1.64 -        _privateKey = privateKey;
    1.65 -    } else {
    1.66 -        SecKeychainItemDelete((SecKeychainItemRef)privateKey);
    1.67 -        CFRelease(privateKey);
    1.68 -    }
    1.69 -    return self;
    1.70 -}
    1.71 -
    1.72 -
    1.73 -// The public API for this is in MYKeychain.
    1.74 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData 
    1.75 -               privateKeyData: (NSData*)privKeyData
    1.76 -                  forKeychain: (SecKeychainRef)keychain 
    1.77 -                   alertTitle: (NSString*)title
    1.78 -                  alertPrompt: (NSString*)prompt
    1.79 -{
    1.80 -    // Try to import the private key first, since the user might cancel the passphrase alert.
    1.81 -    SecKeyImportExportParameters params = {
    1.82 -        .flags = kSecKeySecurePassphrase,
    1.83 -        .alertTitle = (CFStringRef) title,
    1.84 -        .alertPrompt = (CFStringRef) prompt
    1.85 -    };
    1.86 -    SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,&params);
    1.87 -    return [self _initWithPublicKeyData: pubKeyData privateKey: privateKey forKeychain: keychain];
    1.88 -}
    1.89 -
    1.90 -// This method is for testing, so unit-tests don't require user intervention.
    1.91 -// It's deliberately not made public, to discourage clients from trying to manage the passphrases
    1.92 -// themselves (this is less secure than letting the Security agent do it.)
    1.93 -- (id) _initWithPublicKeyData: (NSData*)pubKeyData 
    1.94 -               privateKeyData: (NSData*)privKeyData
    1.95 -                  forKeychain: (SecKeychainRef)keychain 
    1.96 -                   passphrase: (NSString*)passphrase
    1.97 -{
    1.98 -    SecKeyImportExportParameters params = {
    1.99 -        .passphrase = (CFStringRef) passphrase,
   1.100 -    };
   1.101 -    SecKeyRef privateKey = importKey(privKeyData,kSecItemTypePrivateKey,keychain,&params);
   1.102 -    return [self _initWithPublicKeyData: pubKeyData privateKey: privateKey forKeychain: keychain];
   1.103 -}
   1.104 -
   1.105 -
   1.106 -- (void) dealloc
   1.107 -{
   1.108 -    if (_privateKey) CFRelease(_privateKey);
   1.109 -    [super dealloc];
   1.110 -}
   1.111 -
   1.112 -- (void) finalize
   1.113 -{
   1.114 -    if (_privateKey) CFRelease(_privateKey);
   1.115 -    [super finalize];
   1.116 -}
   1.117 -
   1.118 -
   1.119 -- (NSUInteger)hash {
   1.120 -    // Ensure that a KeyPair doesn't hash the same as its corresponding PublicKey:
   1.121 -    return super.hash ^ 0xFFFFFFFF;
   1.122 -}
   1.123 -
   1.124 -
   1.125 -- (MYPublicKey*) asPublicKey {
   1.126 -    return [[[MYPublicKey alloc] initWithKeyRef: self.keyRef] autorelease];
   1.127 -}
   1.128 -
   1.129 -
   1.130 -- (NSData*) exportPrivateKeyInFormat: (SecExternalFormat)format
   1.131 -                             withPEM: (BOOL)withPEM
   1.132 -                          alertTitle: (NSString*)title
   1.133 -                         alertPrompt: (NSString*)prompt
   1.134 -{
   1.135 -    SecKeyImportExportParameters params = {
   1.136 -        .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,
   1.137 -        .flags = kSecKeySecurePassphrase,
   1.138 -        .alertTitle = (CFStringRef)title,
   1.139 -        .alertPrompt = (CFStringRef)prompt
   1.140 -    };
   1.141 -    CFDataRef data = NULL;
   1.142 -    if (check(SecKeychainItemExport(_privateKey, //$array((id)_publicKey,(id)_privateKey),
   1.143 -                                    format, (withPEM ?kSecItemPemArmour :0), 
   1.144 -                                    &params, &data),
   1.145 -              @"SecKeychainItemExport"))
   1.146 -        return [(id)CFMakeCollectable(data) autorelease];
   1.147 -    else
   1.148 -        return nil;
   1.149 -}
   1.150 -
   1.151 -- (NSData*) exportPrivateKey {
   1.152 -    return [self exportPrivateKeyInFormat: kSecFormatWrappedOpenSSL withPEM: YES
   1.153 -                               alertTitle: @"Export Private Key"
   1.154 -                              alertPrompt: @"Enter a passphrase to protect the private-key file.\n"
   1.155 -            "You will need to re-enter the passphrase later when importing the key from this file, "
   1.156 -            "so keep it in a safe place."];
   1.157 -    //FIX: Should make these messages localizable.
   1.158 -}
   1.159 -
   1.160 -
   1.161 -- (NSData*) _exportPrivateKeyInFormat: (SecExternalFormat)format
   1.162 -                              withPEM: (BOOL)withPEM
   1.163 -                           passphrase: (NSString*)passphrase
   1.164 -{
   1.165 -    SecKeyImportExportParameters params = {
   1.166 -        .version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,
   1.167 -        .passphrase = (CFStringRef)passphrase
   1.168 -    };
   1.169 -    CFDataRef data = NULL;
   1.170 -    if (check(SecKeychainItemExport(_privateKey,
   1.171 -                                    format, (withPEM ?kSecItemPemArmour :0), 
   1.172 -                                    &params, &data),
   1.173 -              @"SecKeychainItemExport"))
   1.174 -        return [(id)CFMakeCollectable(data) autorelease];
   1.175 -    else
   1.176 -        return nil;
   1.177 -}
   1.178 -
   1.179 -- (BOOL) removeFromKeychain {
   1.180 -    return check(SecKeychainItemDelete((SecKeychainItemRef)_privateKey), @"delete private key")
   1.181 -        && [super removeFromKeychain];
   1.182 -}
   1.183 -
   1.184 -
   1.185 -- (SecKeyRef) privateKeyRef {
   1.186 -    return _privateKey;
   1.187 -}
   1.188 -
   1.189 -
   1.190 -- (NSData*) decryptData: (NSData*)data {
   1.191 -    return _crypt(_privateKey,data,kCCDecrypt);
   1.192 -}
   1.193 -    
   1.194 -
   1.195 -- (NSData*) signData: (NSData*)data {
   1.196 -    Assert(data);
   1.197 -    uint8_t digest[CC_SHA256_DIGEST_LENGTH];
   1.198 -    CC_SHA256(data.bytes,data.length, digest);
   1.199 -    
   1.200 -    NSData *signature = nil;
   1.201 -    CSSM_CC_HANDLE ccHandle = cssmCreateSignatureContext(_privateKey);
   1.202 -    if (!ccHandle) return nil;
   1.203 -    CSSM_DATA original = {data.length, (void*)data.bytes};
   1.204 -    CSSM_DATA result = {0,NULL};
   1.205 -    if (checkcssm(CSSM_SignData(ccHandle, &original, 1, CSSM_ALGID_NONE, &result), @"CSSM_SignData"))
   1.206 -        signature = [NSData dataWithBytesNoCopy: result.Data length: result.Length
   1.207 -                                   freeWhenDone: YES];
   1.208 -    CSSM_DeleteContext(ccHandle);
   1.209 -    return signature;
   1.210 -}
   1.211 -
   1.212 -
   1.213 -- (BOOL) setValue: (NSString*)valueStr ofAttribute: (SecKeychainAttrType)attr {
   1.214 -    return [super setValue: valueStr ofAttribute: attr]
   1.215 -        && [[self class] _setAttribute: attr 
   1.216 -                                ofItem: (SecKeychainItemRef)_privateKey
   1.217 -                           stringValue: valueStr];
   1.218 -}
   1.219 -
   1.220 -
   1.221 -@end
   1.222 -
   1.223 -
   1.224 -#endif !MYCRYPTO_USE_IPHONE_API
   1.225 -
   1.226 -
   1.227 -
   1.228 -
   1.229 -/*
   1.230 - Copyright (c) 2009, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   1.231 - 
   1.232 - Redistribution and use in source and binary forms, with or without modification, are permitted
   1.233 - provided that the following conditions are met:
   1.234 - 
   1.235 - * Redistributions of source code must retain the above copyright notice, this list of conditions
   1.236 - and the following disclaimer.
   1.237 - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   1.238 - and the following disclaimer in the documentation and/or other materials provided with the
   1.239 - distribution.
   1.240 - 
   1.241 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   1.242 - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   1.243 - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   1.244 - BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   1.245 - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   1.246 -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   1.247 - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   1.248 - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1.249 - */