Month: November 2012

[問題]遇到 PerformSelector may cause a leak because its selector is unknown

這是在使用 ARC 模式下 performSelector 所會遇到的問題

解決辦法:在發生問題的函式上方宣告下面的敘述

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
Tags : ,

[問題]如何在Tomcat安裝多個 webapp (不同domain name) 使用同一個ip

編輯 Server.xml,新增 <Host></Host>

<!-- Tomcat 預設 -->
<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
<!-- 新增 www.mydomainname1.com -->
<Host name="www.mydomainname1.com"  appBase="mydomainname1"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Alias>mydomainname1.com</Alias>
</Host>
!-- 新增 www.mydomainname2.com -->
<Host name="www.mydomainname2.com"  appBase="mydomainname2"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
<Alias>mydomainname2.com</Alias>
</Host>

所存放的目錄結構如下

${TOMCAT_HOME}/webapps/ROOT
${TOMCAT_HOME}/mydomainname1/ROOT
${TOMCAT_HOME}/mydomainname2/ROOT
Tags : ,

[教學]Objective-c LLVM 4.0 新用法

NSNumber

之前用法:

NSNumber *intNumber = [NSNumber numberWithInt:10];
 
NSNumber *doubleNumber = [NSNumber numberWithDouble:1.234567];
 
NSNumber *charNumber = [NSNumber numberWithChar:'x'];
 
NSNumber *boolNumber = [NSNumber numberWithBool:YES];

4.0 後新用法

NSNumber *intNumber = @1000;
 
NSNumber *doubleNumber = @1.234567;
 
NSNumber *charNumber = @'x';
 
NSNumber *boolNumber= @YES;

NSArray

之前用法:

NSArray *weekdays = [NSArray arrayWithObjects:@"monday", @"tuesday", @"wednesday", nil];
 
NSString *monday = [weekdays objectAtIndex:0];

4.0 後新用法

NSArray *weekdays = @[@"monday", @"tuesday", @"wednesday"];
 
NSString *monday = weekdays[0];

NSDictionary

之前用法:

NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:
 
@"ynjan", @"name",
 
@"www.ynjan.com", @"website",
 
nil];
 
NSString *name = [info objectForKey:@"name"];

4.0 後新用法

NSDictionary *info = @{
 
@"name": @"ynjan",
 
@"website": @"www.ynjan.com"
 
};
 
NSString *name = info[@"name"];
Tags : ,

[教學] iOS 上使用 RSA Public Key 加密

使用 openssl 產生 key

private key

openssl genrsa -out private_key.pem 1024

pkcs8 private key

這是程式會用到的 private key

openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

pkcs8_private_key.pem 內容

-----BEGIN RSA PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJavPhrQDMVIVq5wv5WDFGxeWcQk
XW+fsL/z6hui9WRNztAw+NENAuC/tciF9MibGI/sFcRunriGVyKFsIy7QFknKf4zz3E2uE+GPfeV
RyP3SsWN/cj/OU7QaT6mhpa007Niyy40Uy2PqCCbUQlgHCLr65gLwTz9fLjj7noHjRvFAgMBAAEC
gYAuBEplCdA8l0DReOEpGaStC4tCWRCnvA7QL/74faWPAiv8bFgwD1cnp6QuHqqIcMTpfuGO4XFb
TLtjcYxfDfgyR1N6JbnG06oL1MlTmwfZjIrwGfhDurR0cvlNDzTlMyGfHux+0L6Wgujz4WVvC1l8
cIS/L9LkKM6jri336N2AwQJBAPCBe3Izu4izP7iqYq3FjWtW6WJY2BgG1vefnXFN99SRoEVuQLuM
mC3Ol8Tfvt4+mRuFIPA1PgKtrScNbCZlOy0CQQCgZGRzoo8BvSGfg4/v080vXWDAOGz2v6qidFau
RrYNlD26PL+p+kthMQPiEMotcAy3ssfJRhsftqjt5h5K5OH5AkEArQAW8lEwJub5gTZfASzHy1yb
SLkryCyzWTAhqq0xBmEybn8eZUp+9QRUu7NOssNIkzkyNle2IWsY0KyhDQVoiQJBAJUhIwEdSUg9
mTCee8tqrCH4+YdgL3gxd6866ol597Wies5Zw3+A2GuSzmB4afNbdoeqs/XhuECBbopb5xiNvckC
QQCNyF165oFTkWwi7MvD+y8rsatzzVmwiJDOYEpNDSUB7a3pjppairwi8CgDHbDOuoKlDPPYr7rW
LHsJq+0suREU
-----END RSA PRIVATE KEY-----

public key

openssl rsa -in private_key.pem -out public_key.pem -pubout

public_key.pem 內容

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWrz4a0AzFSFaucL+VgxRsXlnEJF1vn7C/8+ob
ovVkTc7QMPjRDQLgv7XIhfTImxiP7BXEbp64hlcihbCMu0BZJyn+M89xNrhPhj33lUcj90rFjf3I
/zlO0Gk+poaWtNOzYssuNFMtj6ggm1EJYBwi6+uYC8E8/Xy44+56B40bxQIDAQAB
-----END PUBLIC KEY-----

加密方式

在 iOS 上有兩種方式可以做到 RSA 加解密的功能

  1. 使用 iOS 內建 Security.framework
  2. 使用 SSCrypto.framework + openssl

Security.framework

設定 public Key

- (NSData *)stripPublicKeyHeader:(NSData *)d_key
{
    // Skip ASN.1 public key header
    if (d_key == nil) return(nil);
 
    unsigned int len = [d_key length];
    if (!len) return(nil);
 
    unsigned char *c_key = (unsigned char *)[d_key bytes];
    unsigned int  idx    = 0;
 
    if (c_key[idx++] != 0x30) return(nil);
 
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
 
    // PKCS #1 rsaEncryption szOID_RSA_RSA
    static unsigned char seqiod[] =
    { 0x30,   0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
     0x01, 0x05, 0x00 };
    if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
 
    idx += 15;
 
    if (c_key[idx++] != 0x03) return(nil);
 
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
 
    if (c_key[idx++] != '\0') return(nil);
 
    // Now make a new NSData from this buffer
    return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}
- (BOOL)addPublicKey:(NSString *)key withTag:(NSString *)tag
{
    NSString *s_key = [NSString string];
    NSArray  *a_key = [key componentsSeparatedByString:@"\n"];
    BOOL     f_key  = FALSE;
 
    for (NSString *a_line in a_key) {
        if ([a_line isEqualToString:@"-----BEGIN PUBLIC KEY-----"]) {
            f_key = TRUE;
        }
        else if ([a_line isEqualToString:@"-----END PUBLIC KEY-----"]) {
            f_key = FALSE;
        }
        else if (f_key) {
            s_key = [s_key stringByAppendingString:a_line];
        }
    }
    if (s_key.length == 0) return(FALSE);
 
    // This will be base64 encoded, decode it.
    NSData *d_key = [NSData dataFromBase64String:s_key];
    d_key = [self stripPublicKeyHeader:d_key];
    if (d_key == nil) return(FALSE);
 
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
 
    // Delete any old lingering key with the same tag
    NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
    [publicKey setObject:(id) kSecClassKey forKey:(id)kSecClass];
    [publicKey setObject:(id) kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
    [publicKey setObject:d_tag forKey:(id)kSecAttrApplicationTag];
    SecItemDelete((CFDictionaryRef)publicKey);
 
    CFTypeRef persistKey = nil;
 
    // Add persistent version of the key to system keychain
    [publicKey setObject:d_key forKey:(id)kSecValueData];
    [publicKey setObject:(id) kSecAttrKeyClassPublic forKey:(id)
     kSecAttrKeyClass];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)
     kSecReturnPersistentRef];
 
    OSStatus secStatus = SecItemAdd((CFDictionaryRef)publicKey, &persistKey);
    if (persistKey != nil) CFRelease(persistKey);
 
    if ((secStatus != noErr) && (secStatus != errSecDuplicateItem)) {
        [publicKey release];
        return(FALSE);
    }
 
    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;
 
    [publicKey removeObjectForKey:(id)kSecValueData];
    [publicKey removeObjectForKey:(id)kSecReturnPersistentRef];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef
    ];
    [publicKey setObject:(id) kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
    secStatus = SecItemCopyMatching((CFDictionaryRef)publicKey,
                                    (CFTypeRef *)&_publicKeyRef);
 
    [publicKey release];
 
    if (_publicKeyRef == nil) return(FALSE);
    return(TRUE);
}

這兩段 stripPublicKeyHeader, addPublicKey 來自 Using an RSA public key generated by OpenSSL in iOS

加密

- (NSData*)encrypt:(NSString*)text {
    OSStatus sanityCheck = noErr;
    size_t cipherBufferSize = 0;
    size_t keyBufferSize = 0;
 
    NSData * data = [text dataUsingEncoding:NSUTF8StringEncoding];    
    NSData * cipher = nil;
    uint8_t * cipherBuffer = NULL;
 
    // Calculate the buffer sizes.
    cipherBufferSize = SecKeyGetBlockSize(_publicKeyRef);
    keyBufferSize = [data length];
 
    // Allocate some buffer space. I don't trust calloc.
    cipherBuffer = malloc( cipherBufferSize * sizeof(uint8_t) );
    memset((void *)cipherBuffer, 0x0, cipherBufferSize);
 
    // Encrypt using the public key.
    sanityCheck = SecKeyEncrypt(_publicKeyRef,
                                kSecPaddingPKCS1,
                                (const uint8_t *)[data bytes],
                                keyBufferSize,
                                cipherBuffer,
                                &cipherBufferSize
                                );
 
    // Build up cipher text blob.
    cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];
 
    if (cipherBuffer) free(cipherBuffer);
 
    return cipher;
}

SSCrypto.framework + openssl [推薦]

使用 openssl 就相對簡單許多

加密

static NSString *publicKey =
@"-----BEGIN PUBLIC KEY-----\n\
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdsg9OlT8nJys9U/ZahRXjgy/0\n\
/KrFpdXdu1I8CLmAb8iONKgtbOhkob/BibZR21dIM9gcuc7NIH9zqptflXmZ9hfJ\n\
f0DivZ9ganPITBSkuM3wni67rT2sBY5bOvrUC7v77RZJYmiUlOCpEWrOJhfN23Vx\n\
wJ4MhnGHHYzUadLF3wIDAQAB\n\
-----END PUBLIC KEY-----";
- (NSData*)encrypt:(NSString*)text {
    //Convert to NSData
    NSData *key1 = [_publicKey dataUsingEncoding:NSASCIIStringEncoding];
 
    SSCrypto *rsa = [[SSCrypto alloc] initWithPublicKey:key1];
    [rsa setClearTextWithString:text];
    NSData *dataEncrypt = [rsa encrypt];
    return dataEncrypt;
}
Tags : , , ,