美文网首页
01---密码学 HASH RSA

01---密码学 HASH RSA

作者: 清风烈酒2157 | 来源:发表于2020-07-13 15:05 被阅读0次

    RSA数学原理

    上世纪70年代产生的一种加密算法。其加密方式比较特殊,需要两个密钥:公开密钥简称公钥(publickey)和私有密钥简称私钥(privatekey)。公钥加密,私钥解密;私钥加密,公钥解密。这个加密算法就是伟大的RSA.

    互质关系:
    如果两个正整数,除了1以外,没有其他公因数,我们就称这两个数是互质关系(coprime)

    欧拉函数

    • 思考

    计算这个值的方式叫做欧拉函数,使用:Φ(n)表示如: 计算8的欧拉函数,和8互质的 1、2、3、4、5、6、7、8 φ(8) = 4 计算7的欧拉函数,和7互质的 1、2、3、4、5、6、7 φ(7) = 6 计算56的欧拉函数 φ(56) = φ(8) * φ(7) = 4 * 6 = 24

    一、当n是质数的时候,φ(n)=n-1
    二、如果n可以分解成两个互质的整数之积,如n=A*B则: φ(A*B)=φ(A)* φ(B)根据以上两点得到: 如果N是两个质数P1P2的乘积则 φ(N)=φ(P1)* φ(P2)=(P1-1)*(P2-1)

    欧拉定理  费马小定理


    image.png

    欧拉定理:一:如果两个正整数mn互质,那么mφ(n)次方减去1,可以被n整除。举例子: 7 15   φ(15) = φ(3) *φ(5) = 2*4 =87**8%15 = 1

    image.png 费马小定理举例子:7 5互质 7 **4%5 = 1! image.png

    公式转换

    image.png

    第一个都知道第二个k 不影响第三个: 两边同时m 
    模反元素举例子: m=4 n=15 φ(15) = 8 
    假设: e = 3   得到 3*d % x = 1 (ed-1)才会被整除 所以求与=1同理: 3*d = k*x +1  红色框替换  m**(e*d) = m得到; 3*d = k*8+1k=4 d=11
    所以:4 **(3*11)%15 = 4;!

    迪菲赫尔曼密钥交换

    image.png

    如果 客户端和服务器规定好 m:3 n:17  
    客户端有个数13 服务器15
    第一步:服务器向客服端发送6 客户端想后台发送12然后得到最后要发送的 10.

    `

    这里有人问?为啥不是3  因为不满足一些关系

    15*13 != k *16 +1;

    image.png

    终端加密

    由于Mac系统内置OpenSSL(开源加密库),所以我们可以直接在终端上使用命令来玩RSA. OpenSSLRSA算法常用指令主要有三个:

    image.png

    终端加密小数据 pem证书不能直接使用 在苹果中 

    1.生成私钥
    openssl genrsa -out private.pem 1024
    
    2.生成公钥
    openssl rsa -in private.pem -pubout -out public.pem
    writing RSA key
    
    cat XXX  查看 
    
    vim message.txt  生成文本 
    
    转成text文本
    openssl rsa -in private.pem -text -out private.text
    writing RSA key 
    公钥加密:
    openssl rsautl -encrypt -in message.txt -inkey public.pem -pubin -out enc.txt
    私钥解密
    openssl rsautl -decrypt -in enc.txt -inkey private.pem -out dec.txt
    
    证书生成  csr cer 
    
    csr请求文件 
    openssl req -new -key private.pem -out rsacert.csr 
    
    签名 https协议 用这个签名 放在服务器   —>公钥 
    openssl x509 -req -days 3650 -in rsacert.csr -signkey private.pem -out rsacert.crt
    
    生成p12文件   —>私钥
    openssl pkcs12 -export -out p.p12 -inkey private.pem -in rsacert.crt
    
    crt后面要变成der文件 苹果才支持使用
    
    openssl x509 -outform der -in rsacert.crt -out rsacert.cer
    

    base64

    //  base64 可以将任意的二进制数据进行编码。 编码成为65个字符组成的文本文件。
    //  0 ~ 9 a ~ z, A ~ Z + / =
    // $base64 源文件 -o 目标文件    编码
    // $base64 源文件 -o 目标文件 -D 解码
    //  101001 010101 010100 010101
    //  A 字节   =  =
    //  010000 010000 000000 000000
    
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSLog(@"%@",[self base64Encode:@"A"]);
        NSLog(@"解码:%@",[self base64Decode:@"QQ=="]);
        
    }
    -(NSString *)base64Encode:(NSString *)string{
        //
        NSData * data = [string dataUsingEncoding:NSUTF8StringEncoding];
        return [data base64EncodedStringWithOptions:0];
    }
    -(NSString *)base64Decode:(NSString *)str{
        NSData * data = [[NSData alloc] initWithBase64EncodedString:str options:0];
        return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    }
    @end
    

    RSA代码演示

    #import <Foundation/Foundation.h>
    @interface RSACryptor : NSObject
        
    + (instancetype)sharedRSACryptor;
        
        /**
         *  生成密钥对
         *
         *  @param keySize 密钥尺寸,可选数值(512/1024/2048)
         */
    - (void)generateKeyPair:(NSUInteger)keySize;
        
        /**
         *  加载公钥
         *
         *  @param publicKeyPath 公钥路径
         *
         @code
         # 生成证书
         $ openssl genrsa -out ca.key 1024
         # 创建证书请求
         $ openssl req -new -key ca.key -out rsacert.csr
         # 生成证书并签名
         $ openssl x509 -req -days 3650 -in rsacert.csr -signkey ca.key -out rsacert.crt
         # 转换格式
         $ openssl x509 -outform der -in rsacert.crt -out rsacert.der
         @endcode
         */
    - (void)loadPublicKey:(NSString *)publicKeyPath;
        
        /**
         *  加载私钥
         *
         *  @param privateKeyPath p12文件路径
         *  @param password      p12文件密码
         *
         @code
         openssl pkcs12 -export -out p.p12 -inkey ca.key -in rsacert.crt
         @endcode
         */
    - (void)loadPrivateKey:(NSString *)privateKeyPath password:(NSString *)password;
        
        /**
         *  加密数据
         *
         *  @param plainData 明文数据
         *
         *  @return 密文数据
         */
    - (NSData *)encryptData:(NSData *)plainData;
        
        /**
         *  解密数据
         *
         *  @param cipherData 密文数据
         *
         *  @return 明文数据
         */
    - (NSData *)decryptData:(NSData *)cipherData;
        
    @end
    
    #import "RSACryptor.h"
    // 填充模式  kSecPaddingNone 每次解密结果是固定的
    //          kSecPaddingPKCS1 是随机变化的。
    #define kTypeOfWrapPadding        kSecPaddingNone
    // 公钥/私钥标签
    #define kPublicKeyTag            "com.logic.EncryptDemo.publickey"
    #define kPrivateKeyTag            "com.logic.EncryptDemo.privatekey"
    static const uint8_t publicKeyIdentifier[]        = kPublicKeyTag;
    static const uint8_t privateKeyIdentifier[]        = kPrivateKeyTag;
    @interface RSACryptor() {
        SecKeyRef publicKeyRef;                             // 公钥引用
        SecKeyRef privateKeyRef;                            // 私钥引用
    }
        
        @property (nonatomic, retain) NSData *publicTag;        // 公钥标签
        @property (nonatomic, retain) NSData *privateTag;       // 私钥标签
        
        @end
    @implementation RSACryptor
        
    + (instancetype)sharedRSACryptor {
        static id instance;
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[self alloc] init];
        });
        return instance;
    }
        
    - (instancetype)init {
        self = [super init];
        if (self) {
            // 查询密钥的标签
            _privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)];
            _publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
        }
        return self;
    }
        
    #pragma mark - 加密 & 解密数据
    - (NSData *)encryptData:(NSData *)plainData {
        OSStatus sanityCheck = noErr;
        size_t cipherBufferSize = 0;
        size_t keyBufferSize = 0;
        
        NSAssert(plainData != nil, @"明文数据为空");
        NSAssert(publicKeyRef != nil, @"公钥为空");
        
        NSData *cipher = nil;
        uint8_t *cipherBuffer = NULL;
        
        // 计算缓冲区大小
        cipherBufferSize = SecKeyGetBlockSize(publicKeyRef);
        keyBufferSize = [plainData length];
        
        if (kTypeOfWrapPadding == kSecPaddingNone) {
            NSAssert(keyBufferSize <= cipherBufferSize, @"加密内容太大");
        } else {
            NSAssert(keyBufferSize <= (cipherBufferSize - 11), @"加密内容太大");
        }
        
        // 分配缓冲区
        cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
        memset((void *)cipherBuffer, 0x0, cipherBufferSize);
        
        // 使用公钥加密
        sanityCheck = SecKeyEncrypt(publicKeyRef,
                                    kTypeOfWrapPadding,
                                    (const uint8_t *)[plainData bytes],
                                    keyBufferSize,
                                    cipherBuffer,
                                    &cipherBufferSize
                                    );
        
        NSAssert(sanityCheck == noErr, @"加密错误,OSStatus == %d", sanityCheck);
        
        // 生成密文数据
        cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];
        
        if (cipherBuffer) free(cipherBuffer);
        
        return cipher;
    }
        
    - (NSData *)decryptData:(NSData *)cipherData {
        OSStatus sanityCheck = noErr;
        size_t cipherBufferSize = 0;
        size_t keyBufferSize = 0;
        
        NSData *key = nil;
        uint8_t *keyBuffer = NULL;
        
        SecKeyRef privateKey = NULL;
        
        privateKey = [self getPrivateKeyRef];
        NSAssert(privateKey != NULL, @"私钥不存在");
        
        // 计算缓冲区大小
        cipherBufferSize = SecKeyGetBlockSize(privateKey);
        keyBufferSize = [cipherData length];
        
        NSAssert(keyBufferSize <= cipherBufferSize, @"解密内容太大");
        
        // 分配缓冲区
        keyBuffer = malloc(keyBufferSize * sizeof(uint8_t));
        memset((void *)keyBuffer, 0x0, keyBufferSize);
        
        // 使用私钥解密
        sanityCheck = SecKeyDecrypt(privateKey,
                                    kTypeOfWrapPadding,
                                    (const uint8_t *)[cipherData bytes],
                                    cipherBufferSize,
                                    keyBuffer,
                                    &keyBufferSize
                                    );
        
        NSAssert1(sanityCheck == noErr, @"解密错误,OSStatus == %d", sanityCheck);
        
        // 生成明文数据
        key = [NSData dataWithBytes:(const void *)keyBuffer length:(NSUInteger)keyBufferSize];
        
        if (keyBuffer) free(keyBuffer);
        
        return key;
    }
        
    #pragma mark - 密钥处理
        /**
         *  生成密钥对
         */
    - (void)generateKeyPair:(NSUInteger)keySize {
        OSStatus sanityCheck = noErr;
        publicKeyRef = NULL;
        privateKeyRef = NULL;
        
        NSAssert1((keySize == 512 || keySize == 1024 || keySize == 2048), @"密钥尺寸无效 %tu", keySize);
        
        // 删除当前密钥对
        [self deleteAsymmetricKeys];
        
        // 容器字典
        NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];
        
        // 设置密钥对的顶级字典
        [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
        [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];
        
        // 设置私钥字典
        [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
        [privateKeyAttr setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
        
        // 设置公钥字典
        [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
        [publicKeyAttr setObject:_publicTag forKey:(__bridge id)kSecAttrApplicationTag];
        
        // 设置顶级字典属性
        [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
        [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];
        
        // SecKeyGeneratePair 返回密钥对引用
        sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef);
        NSAssert((sanityCheck == noErr && publicKeyRef != NULL && privateKeyRef != NULL), @"生成密钥对失败");
    }
        
        /**
         *  加载公钥
         */
    - (void)loadPublicKey:(NSString *)publicKeyPath {
        
        NSAssert(publicKeyPath.length != 0, @"公钥路径为空");
        // 删除当前公钥
        if (publicKeyRef) CFRelease(publicKeyRef);
        
        // 从一个 DER 表示的证书创建一个证书对象
        NSData *certificateData = [NSData dataWithContentsOfFile:publicKeyPath];
        SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
        NSAssert(certificateRef != NULL, @"公钥文件错误");
        
        // 返回一个默认 X509 策略的公钥对象,使用之后需要调用 CFRelease 释放
        SecPolicyRef policyRef = SecPolicyCreateBasicX509();
        // 包含信任管理信息的结构体
        SecTrustRef trustRef;
        
        // 基于证书和策略创建一个信任管理对象
        OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
        NSAssert(status == errSecSuccess, @"创建信任管理对象失败");
        
        // 信任结果
        SecTrustResultType trustResult;
        // 评估指定证书和策略的信任管理是否有效
        status = SecTrustEvaluate(trustRef, &trustResult);
        NSAssert(status == errSecSuccess, @"信任评估失败");
        
        // 评估之后返回公钥子证书
        publicKeyRef = SecTrustCopyPublicKey(trustRef);
        NSAssert(publicKeyRef != NULL, @"公钥创建失败");
        
        if (certificateRef) CFRelease(certificateRef);
        if (policyRef) CFRelease(policyRef);
        if (trustRef) CFRelease(trustRef);
    }
        
        /**
         *  加载私钥
         */
    - (void)loadPrivateKey:(NSString *)privateKeyPath password:(NSString *)password {
        
        NSAssert(privateKeyPath.length != 0, @"私钥路径为空");
        
        // 删除当前私钥
        if (privateKeyRef) CFRelease(privateKeyRef);
        
        NSData *PKCS12Data = [NSData dataWithContentsOfFile:privateKeyPath];
        CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
        CFStringRef passwordRef = (__bridge CFStringRef)password;
        
        // 从 PKCS #12 证书中提取标示和证书
        SecIdentityRef myIdentity;
        SecTrustRef myTrust;
        const void *keys[] =   {kSecImportExportPassphrase};
        const void *values[] = {passwordRef};
        CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
        CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
        
        // 返回 PKCS #12 格式数据中的标示和证书
        OSStatus status = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
        
        if (status == noErr) {
            CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
            myIdentity = (SecIdentityRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
            myTrust = (SecTrustRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
        }
        
        if (optionsDictionary) CFRelease(optionsDictionary);
        
        NSAssert(status == noErr, @"提取身份和信任失败");
        
        SecTrustResultType trustResult;
        // 评估指定证书和策略的信任管理是否有效
        status = SecTrustEvaluate(myTrust, &trustResult);
        NSAssert(status == errSecSuccess, @"信任评估失败");
        
        // 提取私钥
        status = SecIdentityCopyPrivateKey(myIdentity, &privateKeyRef);
        NSAssert(status == errSecSuccess, @"私钥创建失败");
    }
        
        /**
         *  删除非对称密钥
         */
    - (void)deleteAsymmetricKeys {
        OSStatus sanityCheck = noErr;
        NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init];
        NSMutableDictionary *queryPrivateKey = [[NSMutableDictionary alloc] init];
        
        // 设置公钥查询字典
        [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
        [queryPublicKey setObject:_publicTag forKey:(__bridge id)kSecAttrApplicationTag];
        [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
        
        // 设置私钥查询字典
        [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
        [queryPrivateKey setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
        [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
        
        // 删除私钥
        sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPrivateKey);
        NSAssert1((sanityCheck == noErr || sanityCheck == errSecItemNotFound), @"删除私钥错误,OSStatus == %d", sanityCheck);
        
        // 删除公钥
        sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPublicKey);
        NSAssert1((sanityCheck == noErr || sanityCheck == errSecItemNotFound), @"删除公钥错误,OSStatus == %d", sanityCheck);
        
        if (publicKeyRef) CFRelease(publicKeyRef);
        if (privateKeyRef) CFRelease(privateKeyRef);
    }
        
        /**
         *  获得私钥引用
         */
    - (SecKeyRef)getPrivateKeyRef {
        OSStatus sanityCheck = noErr;
        SecKeyRef privateKeyReference = NULL;
        
        if (privateKeyRef == NULL) {
            NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init];
            
            // 设置私钥查询字典
            [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
            [queryPrivateKey setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
            [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
            [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
            
            // 获得密钥
            sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKeyReference);
            
            if (sanityCheck != noErr) {
                privateKeyReference = NULL;
            }
        } else {
            privateKeyReference = privateKeyRef;
        }
        
        return privateKeyReference;
    }
        
    @end
    

    RSA使用

    
    
    #import "ViewController.h"
    #import "RSACryptor.h"
    @interface ViewController ()
    @end
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //1.加载公钥
        [[RSACryptor sharedRSACryptor] loadPublicKey: [[NSBundle mainBundle] pathForResource:@"rsacert.der" ofType:nil]];
        //2.加载私钥
        [[RSACryptor sharedRSACryptor] loadPrivateKey:[[NSBundle mainBundle] pathForResource:@"p.p12" ofType:nil] password:@"123456"];
        
    }
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        //1.加密
        NSData * result = [[RSACryptor sharedRSACryptor] encryptData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding]];
        NSLog(@"加密的结果是:%@",[result base64EncodedStringWithOptions:0]);
        
        //2.解密
        NSData * jiemi = [[RSACryptor sharedRSACryptor] decryptData:result];
        NSLog(@"解密的结果:%@",[[NSString alloc] initWithData:jiemi encoding:NSUTF8StringEncoding]);
    }
    @end
    

    相关文章

      网友评论

          本文标题:01---密码学 HASH RSA

          本文链接:https://www.haomeiwen.com/subject/fdiacktx.html