随机数序列

本文介绍了如何使用RSA算法高效地生成不重复的随机数序列,适用于大规模端口扫描等场景。通过RSA加密原理,确保每次生成的随机数都是唯一的,并提供了C++代码实现。
摘要由CSDN通过智能技术生成

高效伪随机数序列生成方案

  • 解决(不重复的生成上亿伪随机数),并且不需要记录和比对生成过的随机数

前言

  • 前段时间开发过一个快速端口扫描的模块,需求是要对大批量主机进行端口扫描。端口扫描技术已经是被无数人玩过的了,快速端口扫描主要的技术就是syn扫描,比较成熟。但在大批量扫描的时候,为了降低对目标安全设备的警报(常见的防火墙会通过连接并发数,端口的连接顺序,连接间隔时间来做警报),一般会选择随机的端口扫描。不过因为syn的特性,所以几个目标随机扫描基本没什么意义(发包太快),但是如果是大批量次的扫描,随机就会有意义。如有10个B段要扫描,每个B段的发包数量就是255*255*65535=4261413375(非常大,一般不会傻傻的扫描那么大),每次都随机的从10个段中选择一个段,然后从这个段中随机的选择一个目标,因为扫描的基数大,所以对每个目标重复扫描的间隔时间就会相对比较长,从而减少安全设备的警告
  • 正常情况,大多数人第一反应想到的是洗牌算法,或每次保存生成的随机数,第二次对生成的随机数进行去重查找,如果已经生成过,就继续生成,直到不重复。这些随机数序列生成算法在小范围内是非常高效的,但要生成上亿的随机数序列,并且每次生成的随机数都不重复,使用这些算法就会非常消耗内存和时间,基本不可接受。前期的做法是通过对一个大范围的段拆分为无数个小范围的段,然后一次对10或20个小范围的段进行随机扫描,这样对内存和时间的消耗勉强可以接受,但拆分的过程也是很消耗时间和空间的,整体效率和效果不高
  • 注意:因为IP段其实就是一段连续的无符号整数(在主机字节序的情况下),如一个B段(119.41.0.0-119.41.255.255)要扫描全端口(65535),他的扫描范围就是1-4261413375,只要从1-4261413375范围中随机选择一个数,就可以通过这个数计算出对应的IP与端口,所以只要有1-4261413375范围的随机数序列,就可以高效的进行随机扫描(前提是算法时空效率高)
  • 通过一段时间的查找,终于找到自己满意的算法http://www.cnblogs.com/Geometry/archive/2011/01/25/1944582.html,这个算法的主要思路是通过加密与随机的相通性来实现。如将一个数加密为另一个数,这与随机算法达到的效果很相似,那么如果将1-4261413375中的每一个数都进行加密,就可以得到一个随机的序列。另外随机数的变化是通过初始种子,加密的变化是通过密钥,那么看起来通过改造一个加密算法来实现随机效果,是可以行的。
  • http://www.cnblogs.com/Geometry/archive/2011/01/25/1944582.html中是通过RSA算法来实现伪随机数序列生成,并且此加密算法的特性已经保证每次产生的随机数都是不重复的(有重复还咋解密),最主要的是,在生成1-N范围内的随机数时,生成N次,即可全覆盖1-N(N太大就需要使用大数运算),整体效果还是非常好。

RSA算法简介

RSA加密解密的基本原理

  1. 选取随机的初始大素数:(p,q),注意:p与q不相等
  2. 计算模数N:(N = p * q)
  3. 计算欧拉φ(n):(φ(n) = (p - 1) * (q - 1))
  4. 计算公钥指数e:(1 < e < φ(n) 且 gcd(e,φ(n)) = 1),即e与φ(n)互质,一般选择的e都是比较小的数,主要是为了提升计算速度,毕竟大数运算是很消耗时间的
  5. 计算私钥指数d:(e * d) % φ(n) = 1,即d是e的模反元素
  6. 组合密钥:(n,e)组成公钥,(n,d)组成私钥
  7. 加密:假设A是明文,C是密文,(C = A^e % N),即A的e次幂模N等于C。注意:如果e过大,很容易产生计算漏出,另外使用模幂运算,可有效减少计算漏洞并加速计算
  8. 解密:(A = C^d % N),即C的d次幂模N等于A

RSA安全性

  • RSA的安全性主要体现在大数N分解难度,通过上面可看出e与d是密钥的关键,在知道了e与N的情况下,要计算出d就需要对N分解来得出p和q,目前公布的对N分解最高的二进制位数是768位。

RSA算法生成随机序列的难点

  • 利用RSA来做随机数序列生成的难点也是分解N,但这个N往往是非常小的(相对于加密的安全性来说),因为我们不需要考虑安全性,只需要考虑随机数序列的范围,所以也不是特别麻烦。另外我们只能得到一个随机数范围的参数如1-4261413375,此时Na=4261413375(假设Na为用户输入的随机数序列范围参数),需要对Na分解来得到p,q,然后重新计算出RSA的N。

RSA算法应用于随机数序列生成的基本原理

  1. **用户输入随机数序列范围:**Na,如Na = 4261413375,即生成1-4261413375范围的随机数序列
  2. 分解Na:由于Na是一个用户输入的自然数,而分解质因数是针对合数,另外分解后的p与q是质数并且不相等,并且大多数据情况分解出来的因数会是多个,所以需要循环累加分解,直到找到合适的p和q。通过测试对亿大小的数分解还是很快速的
  3. 得出p和q后,其它步骤与RSA算法加密流程一样。注意:随机数生成只需要使用到RSA加密部分,所以只需要计算出e即可
  4. 注意:如果在同一范围内,想要每次生成的随机数序列都不一样,可以改变e来实现

具体C++代码实现

  • 这里没有使用大数运算,在使用的时候需要注意。经过测试在1亿的范围内生成随机数序列是没问题的,如果有需要提高范围的,加入大数运算也不难,主要是在模幂运算的时候使用大数即可
  • 注意:如果n过小,就不能使用此算法生成随机序列,如n<=6的时候,因为无法计算有效的e,所以无法生成无序的随机数序列
  • 如果代码有什么问题或有更好的方法请告知
  • radom_integer_iterator.h 文件
#ifndef RADOM_INTEGER_ITERATOR_H_H
#define RADOM_INTEGER_ITERATOR_H_H
// 这是一个伪随机序列数迭代生成器,用于解决快速迭代1-n范围内的随机序列(这个n最好在1亿内,否则需要做大数运算),并且保证每次生成的随机数不重复,在迭代n次后,保证序列能覆盖1-n的所有数
// 此随机序列迭代生成算法使用的是rsa加密算法(加密的特性使他天生具有生成随机数的能力),优点是速度快,内存占用极低
// 此随机数适用场景多,比如用于随机扫描一个B段IP端口时,此随机迭代器就能非常完美的解决
// 由于没有使用大数库,请注意n的范围,防止漏出
// 只需要利用rsa的加密部分就可以实现,所以这只里需要计算出p,q,e和新的n就可以,不需要再计算d来解密
#include <vector>
using std::vector;
#include <stdlib.h>
#include <time.h>
// 范围限制宏,即限制用户输入的n,最大不可以超过宏指定的数
#define KOOK_MAX_RADOM_INTEGER_N 100000000
namespace kook {
    // 保存pq值
    typedef struct _RSAPQ {
        unsigned long long rsap;
        unsigned long long rsaq;
        _RSAPQ() :rsap(0), rsaq(0) {};
    }rsapq;
    // 随机序列迭代对象
    // 当n<=6的时候,将不能产生出随机序列,因为无法生成有效的e
    class radom_integer_iterator {
    public:
        radom_integer_iterator() : n(0), rn(0), re(0), i(1) {}
        // 通过unsigned long来限制用户输入过大
        radom_integer_iterator(unsigned long n);
        // 分解质因数,把一个合数分解成若干个质因数的乘积的形式,即求质因数的过程叫做分解质因数(分解质因数只针对合数)
        // 合数指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数
        static vector<unsigned long long> decompose_prime_factor(unsigned long long x);
        // 判断一个数是否是质数
        static bool is_prime_number(unsigned long long x);
        // 计算 a * b % n
        static unsigned long long mul_mod(unsigned long long a, unsigned long long b, unsigned long long n);
        // 模幂运算是RSA的核心算法,直接决定RSA算法的性能,通常都是先将幂模运算转化为乘模运算
        // 返回值 x = base^pow mod n
        static unsigned long long pow_mod(unsigned long long base, unsigned long long po
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值