RSA算法原理精简版介绍

一:RSA 数学理论基础

1. 互质关系

如果两个正整数,除了1以外,没有其他公因子,我们就称这两个数是互质关系(coprime)。比如,15和32没有公因子,所以它们是互质关系。这说明,不是质数也可以构成互质关系。

2. 欧拉函数

请思考以下问题:

任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?(比如,在1到8之中,有多少个数与8构成互质关系?)

计算这个值的方法就叫做欧拉函数,以φ(n)表示。在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = 4。

对于:
因为任意一个大于1的正整数n,都可以写成一系列质数的积。


乘积公式1

上述公式其中p1,p2...pr 都是质数,k1,k2...kr表明是幂。

那么最终欧拉函数公式:


欧拉函数公式2

其中p1,p2....pr 是n的质数因子

3. 数论的欧拉定理

如果两个正整数a和n互质,则n的欧拉函数 φ(n) 可以让下面的等式成立:


数论欧拉定理公式3

也就是:

pow(a, φ(n) ) % n = 1
a的φ(n) 次幂 对 n 取余数是 恒等于 1

4. 模反元素

如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1。


模反元素公式4

这时,b就叫做a的"模反元素"。

注意

如果是要整篇文章描述的更清晰,这里应该这样描述比较好:
对于一个整数n(在RSA算法中是两个非常大质数的乘积), 它的φ(n)是N,如果一个正整数a(1 即: ab % N = 1
下面介绍的计算模反元素是对φ(n)计算而不是对n计算,切记!!!!

把上面的a理解成e(encrypt,加密),b理解成d(decrypt,解密), y是除法的结果
ed % n = 1
ed = yn + 1
这是一个二元一次方程

根据3和4 的公式 可以得知:
b的其中之一 就是:
a的 φ(n)-1 次方,即 b = pow(a, (φ(n)-1))

公钥与私钥

根据公式3:e 的 φ(n)次幂 对 n 取余 等于1,即 pow(e, φ(n)) % n = 1
根据公式4:ed 对 n 取余 等于1,即 ed % n = 1

公钥: n和e组成的字符串,e是跟φ(n)互质
私钥: n和d组成的字符串,d是模反元素

对于明文m,用公钥(n,e)加密 计算密文c

c = pow (m, e) % n

对于密文c,用私钥(n,d)解密 计算明文m

m = pow(c, d) % n

二:RSA 算法简单验证

1. 随机选择两个不相等的质数p和q。

例如选择了61和53。(实际应用中,这两个质数越大,就越难破解。)

    int p = 61;
    int q = 53;

2. 计算p和q的乘积得到n

int n = p * q;

3. 计算n的欧拉函数φ(n)

根据公式:

φ(n) = (p-1)(q-1)

// 数论中的欧拉函数证明过程非常复杂,其中之一的结论是:
// 对n求欧拉函数,n = p * q, 且p和q都是质数
- (int)Euler_functionWithN:(int)n p:(int)p q:(int)q {
    return (p - 1) * (q - 1);
}

4. 随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质

- (int)calculate_random_valueWithEulerFunctionResult:(int)eulerFunctionResult {
    NSMutableArray *ary = [NSMutableArray new];
    BOOL find17 = NO;
    // 加一个i < 100 控制一下列出所有的数据了
    for (int i = 2; i < eulerFunctionResult && i < 100; i++) {
        if (eulerFunctionResult % i != 0) {
            [ary addObject:@(i)];
            if (!find17 && i == 17) {
                find17 = YES;
            }
        }
    }
    NSLog(@"find17:%@", find17 ? @"YES" : @"NO");
    NSLog(@"ary:%@", [ary componentsJoinedByString:@","]);
    return 17;
}

其中的输出结果:

find17:YES
ary:7,9,11,14,17,18,19,21,22,23,25,27,28,29,31,32,33,34,35,36,37,38,41,42,43,44,45,46,47,49,50,51,53,54,55,56,57,58,59,61,62,63,64,66,67,68,69,70,71,72,73,74,75,76,77,79,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99

17 只是众多结果之一

5. 计算e对于φ(n)的模反元素d

// 计算模反元素
- (int)calculate_Mofan_elementWith_eulerFunctionResult:(int)eulerFunctionResult andE:(int)e {
    int x = 0; int y = 0;
    // 模反元素计算公式: (e * x) + eulerFunctionResult * y = 1;
    // 要保证x是正数,那么y就必须是负数,所以从y负一开始
    NSMutableArray *ary = [NSMutableArray new];
    int d = 0;
    int yMax = -200;
    for (y = -1; y > yMax; y--) {
        int tmp = 1 - y * eulerFunctionResult;
        if (tmp % e == 0) {
            x = tmp / e;
            [ary addObject:@(x)];
            if (x == 2753) {
                d = 2753;
            }
        }
    }
    NSLog(@"possibility mofan:%@", ary);
    return d;
}

输出结果(y在-1之-200之间):

possibility mofan:(
    2753,
    5873,
    8993,
    12113,
    15233,
    18353,
    21473,
    24593,
    27713,
    30833,
    33953
)

6. 对明文m使用公钥(n,e)加密得到密文c

// 计算加密
// c = pow(m, e) % n
// 参数: m: 明文,e:公钥的e,n:公钥的n
// 返回值 c: 密文
// 数据太大,pow(m, e)会溢出,所以采取如下的算法
- (int)calculate_encryptWithM:(int)m n:(int)n e:(int)e {
    int c = m;
    for (int i = 1; i < e; i ++) {
        c = c * m;
        if (c > n) {
            c = c % n;
        }
    }
    return c;
}

7. 对密码c使用私钥(n,d)得到明文m

// 计算解密
// decrypt = pow(c, d) % n
// 参数: c: 密文,e:私钥的d,n:私钥的n(跟公钥的n是一样的)
// 返回值 m: 明文
- (int)calculate_decryptWithC:(int)c n:(int)n d:(int)d {
    int m = c;
    for (int i = 1; i < d; i ++) {
        m = m * c;
        if (m > n) {
            m = m % n;
        }
    }
    return m;
}

8. 整个测试demo

- (void)test_encrypt_decrypt_exampleWithM:(int)m n:(int)n publicE:(int)e privateD:(int)d {
    // 密文
    int c = [self calculate_encryptWithM:m n:n e:e];
    NSLog(@"m:%d, c:%d", m, c);
    // 解密后的密文
    int newM = [self calculate_decryptWithC:c n:n d:d];
    NSLog(@"m:%d, newM:%d", m, newM);
}
- (void)test {
    // 第一步,随机选择两个不相等的质数p和q
    int p = 61;
    int q = 53;
    // 第二步,计算p和q的乘积得到n
    int n = p * q;
    // 第三步,计算n的欧拉函数得到eulerFunctionResult
    int eulerFunctionResult = [self Euler_functionWithN:n p:p q:q];
    // 第四步,随机选择一个整数e,1 < e < eulerFunctionResult, 且e与eulerFunctionResult互质
    int e = [self calculate_random_valueWithEulerFunctionResult:eulerFunctionResult];
    // 第五步,计算e与eulerFunctionResult的模反元素d
    int d = [self calculate_Mofan_elementWith_eulerFunctionResult:eulerFunctionResult andE:e];
    
    NSLog(@"p:%d, q:%d, n:%d, eulerFunctionResult:%d, e:%d, d:%d", p, q, n, eulerFunctionResult, e, d);
    NSString *publicKey = [NSString stringWithFormat:@"%d-%d", n, e];
    NSString *privateKey = [NSString stringWithFormat:@"%d-%d", n, d];
    NSLog(@"publicKey:%@, privateKey:%@", publicKey, privateKey);
    
    // 明文 m
    int m = 65;
    
    [self test_encrypt_decrypt_exampleWithM:m n:n publicE:e privateD:d];
}

以上就是RSA算法的总结。

本文参考:
RSA算法原理(一)
RSA算法原理(二)

你可能感兴趣的:(RSA算法原理精简版介绍)