//
//  ViewController.m
//  rsaDemo
//
//  Created by userkuma on 15/3/6.
//  Copyright (c) 2015年 userkuma. All rights reserved.
//

#import "ViewController.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/pem.h>//如果出现警告，自行修改Header Search Paths
#include <openssl/rsa.h>

#define kPublicKeyFile [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"pem"] //公钥路径
#define kPrivateKeyFile [[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"pem"] //私钥路劲

#define kPublicKeyTxt "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALMLzuzNr6t+OgQixmQxzxaNpeN83mfK\nOZ6sZf6R+wnID+MsxLR2rZXhpMtWn4kDwnCSALbThjw7vGbSgTgtDqMCAwEAAQ==\n-----END PUBLIC KEY-----\n"//注意每64位要一个换行符

#define kContentTxt @"kumadocs.com"//需要加密数据

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //密文
    unsigned char encrypted[1024];
    bzero(encrypted, sizeof(encrypted));
    
    //明文
    char decrypted[1024];

    //公钥和私钥文件
    const char* pub_key = [kPublicKeyFile UTF8String];
    const char* priv_key = [kPrivateKeyFile UTF8String];
    
    // -------------------------------------------------------
    // 利用公钥加密明文的过程
    // -------------------------------------------------------
    
    // ---------------------------
    //方法一：从字符串读取RSA公钥
    BIO *bio = NULL;
    RSA *rsa = NULL;
    
    bio = BIO_new_mem_buf(kPublicKeyTxt, -1);
    if (bio == NULL){
        //从字符串读取RSA公钥
        printf("Pub_Key Read Failure!!\n");
    }
    rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
    if (!rsa){
        //从bio结构中得到Rsa结构
        printf("Pub_Key Read Failure!!\n");
    }
    
    NSData *contentData = [kContentTxt dataUsingEncoding:NSASCIIStringEncoding];
    int contentLen = [contentData length];
    unsigned char from[contentLen];
    bzero(from, sizeof(from));
    memcpy(from, [contentData bytes], contentLen);
    
    // 用公钥加密
    int state = RSA_public_encrypt (contentLen, from, encrypted, rsa, RSA_PKCS1_PADDING);
    if( state == -1 ){
        printf("Encrypt Failed!!\n");
        return ;
    }
    
    // ---------------------------
    // 方法二：打开RSA公钥文件
//    RSA *rsa1 = NULL;
//    const char *contentChar = [kContentTxt UTF8String];
//    
//    FILE* pub_fp=fopen(pub_key,"r");
//    if(pub_fp==NULL){
//        printf("Open Failed!! The Pub_Key File : %s!\n", pub_key);
//        return ;
//    }
//    
//    // 从文件中读取公钥
//    rsa1 = PEM_read_RSA_PUBKEY(pub_fp, NULL, NULL, NULL);
//    if(rsa1 == NULL){
//        printf("Pub_Key Read Failure!!\n");
//        return ;
//    }
//    
//    if(strlen(contentChar) >= RSA_size(rsa1)-41){
//        printf("Encrypt Failed!!\n");
//        return ;
//    }
//    fclose(pub_fp);
//    
//    
//    // 用公钥加密
//    int state = RSA_public_encrypt (strlen(contentChar), (const unsigned char*)contentChar, encrypted, rsa1, RSA_PKCS1_PADDING);
//    if( state == -1 ){
//        printf("Encrypt Failed!!");
//        return ;
//    }
    
    
    // ---------------------------
    // 输出加密后的密文
    NSString *encryptedTxt = @"";
    for (int i = 0; i < 128; i++) {//注意128按需要的自行改
        encryptedTxt = [encryptedTxt stringByAppendingFormat:@"%02x",encrypted[i]];
    }
    NSLog(@"encryptedTxt == 》 \n\n%@\n\n",encryptedTxt);
    
    
    
    // -------------------------------------------------------
    // 利用私钥解密密文的过程
    // -------------------------------------------------------
    
    // 打开私钥文件
    FILE* priv_fp=fopen(priv_key,"r");
    if(priv_fp==NULL){
        printf("Open Failed!! The Priv_Key File :%s!\n", priv_key);
        return ;
    }
    
    
    // 从文件中读取私钥
    RSA *rsa2 = PEM_read_RSAPrivateKey(priv_fp, NULL, NULL, NULL);
    if(rsa2==NULL){
        printf("Priv_Key Read Failure!!\n");
        return ;
    }
    
    // 用私钥解密
    state = RSA_private_decrypt(state, encrypted, decrypted, rsa2, RSA_PKCS1_PADDING);
    if(state == -1){
        printf("Decrypt Failed!!\n");
        return ;
    }
    fclose(priv_fp);
    
    
    // 输出解密后的明文
    decrypted[state]=0;
    printf("decrypted == 》%s\n",decrypted);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
