crypt.4.单向函数的陷阱

本文探讨了单向函数的概念及其在加密技术中的应用,特别是通过质因数分解问题的复杂性来保障RSA加密系统的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

from:2017 CCF计算机课程改革导教班. 陈道蓄

14

单向函数的陷阱 – 掉下去就出不来了

我们前面一直在讨论一个算法问题如果能较快的解决。用计算机科学家的话说,如果高效地解决问题。找不到能很快计算的方法似乎让人沮丧。本章我们会看到没有有效解法的问题也可能有很大价值。我们希望传递的信息是:坏消息可能反倒很有好处。

从反射镜中看乘法:因子分解

11章告诉我们两个数相乘可以算得很快,哪怕这两个数非常大,要用许多位数字才能表示。小学中大家就学过计算两个数相乘的简单算法。普通人用纸和笔花几分钟时间就可以计算两个相当大的数的乘积,尽管很乏味还得注意力集中以免出错。对计算机而言,用千分之几秒的时间计算两个几百甚至几千位的数的乘积实在是一件简单之极的事。

                       14.1 单向函数

 

                      14.2 怎么才能回去?

我们来考虑一下逆向的问题:将乘积再还原成原来的乘数。大家还记得有些数被称为素数,它们不能分解为更小的乘法因子。素数表中最前面的数包括2,3,5,7,11,13,17,19,23,…数学家证明任何整数均可表示为唯一的素数乘积的形式。例如:

        20,518,260 = 2×2×3×5×7×7×7×997

我们很自然地会想到这样的问题:如果设计一个算法,找到任意整数的素数因子。这就是质因子分解问题。我们能象做乘法那么方便地解决此问题吗,即使数字很大?

最后一位数N能告诉我们该数是否能被25整除。累加各位数字也能判定该数是否为3的倍数。但对于只有很大很大的质因子的数,这个问题似乎就没那么简单了。古希腊人知道一个方法:用不大于n的平方根的所有素数逐个试除n,由此找出n的质因子。如果n的十进制表示有100为,大约需要试除8.5×1048次。这时间实在难以想象,恐怕在我们宇宙的整个生命期内都算不完。

素数判定问题可以看作质因子分解问题的一个简化的子问题。我们要判定一个给定的数是否为素数,也就是它不可能有更小的质因子。这个问题已有有效算法,不在本章内讨论。可参阅第13章。

1970年三位计算机科学家,Ron Rivest,Adi ShamirLeonard Adleman发明了RSA密码系统。RSA系统加密的文本可以在不安全的通信环境下发送,例如通过互联网,但仍然可以防止第三方探知文本的内容。今天,RSA系统作为基本网络安全工具广为应用。RSA系统选择两个非常大的素数p,q的乘积Npq是保密的。解密的方法与能否知道p,q的值密切相关。

为了显示系统的安全程度,发明者在1977年用129位十进数N加密了一段文本。他们公开了N和密文,欢迎任何人挑战解密。公布的N是:

直到17年后,在1994才开发出了比简单尝试所有的素数是否为因子更聪明的算法。经过8个月在全世界数百台计算机组成的集群上的密集计算,终于发现这两个乘数:

总共执行了1.6×1017也就是160万亿次计算机指令。你想知道被加密的文本的内容吗?

        The magic words are squeamish ossifrage. 魔咒是“呕吐的鱼鹰”

单向函数

今天,又过去了许多年。

坏消息:用已知最好的算法,在现在甚至近期内可能有的最快的计算机上,哪怕是数千台一起用,对于一个只有很大的质因子的几百位的十进数,我们仍然无法在可接受的时间内(比如100)找出它的质因子。

l 好消息:既然没有快速的质因子分解算法,那么RSA方法支持的数据加密,例如网上银行使用的口令,就可以认为是绝对安全的。

我们来总结一下:

1, 两个数相乘,包括两个素数相乘,可以算得非常快。

2, 

而其逆运算,即将一个乘积还原成原来的质因子,计算很困难。至少就目前信息科学与数学能达到的水平是如此。

                           14.3 通过密道返回

如何能利用这种情况呢?数学中函数是指将数学对象转化为另外的对象的操作。我们讨论的对象是数或者数的序列。因子分解可以看作乘法的反函数。

如果一种操作很容易执行,而其反函数则很难,这样的函数称为单向函数。单向函数对文本加密很有用。在需要发送文本M时,我们将单向函数用于对文本M加密,用加密后的文本替代原文本发送给对方。根据单向函数的特性,加密很容易,而用其反函数解密则很难计算。这样攻击者就没有机会将密件还原为文本M

看一个例子。 Alice想向Bob发送信息“Top secret(绝密)”。假设他们只使用大写字母,并用X表示单词之间的空格。用0126对字母编码。这样文本TOPXSECRET被转换为:

                        T = 20151624190503180520

一般而言,这个数未必是素数,但总可以在最右边添加几个数字将其改变成素数。就上面的例子,添加13可以得到一个素数:

                         p = 2015162419050318052013

Alice再选一个更大一些的素数,例如:

                         q = 567891624050318052137

然后计算它们的乘积:

                      N = p×q = 11443938509186566743788165964622411801781

Alice可以将N发送给Bob,不必担心泄密。没有人能对N解密得到p并由此还原出T,因为那就意味着可以分解N的质因子。坦白说,这个例子中用的数不大,还不够安全。实际应用中选择的T至少有150位,AliceT后面再加几位,得到足够大的素数p

可是,这下Bob也没法解密了。唔… , 用单向函数加密也不是那么简单,还得加点儿窍门。

带秘密信息的单向函数f,技术上称为陷门函数,除前面说的两点外,还有第三个特征:

  3. f的反函数在有密钥的条件下很容易计算。

这要求听上去有点奇怪,后面我们将举个日常生活中的例子。

 

 

 

 

 

 

 

 

                      14.4 在密码通信中使用陷门函数

一个实际例子:查阅电话号码簿

回想若干年前,网上的电子数据库还不存在,查电话号码必须使用纸质的号码簿。如果Alice想给多日未曾联系的老朋友Bob打电话,但不知道Bob现在的电话号码。Alice只须在电话号码簿中找Bob的名字,名字后面列的就是她要的号码。这很简单,也很快,为什么?

1章介绍过二分搜索。以德国城市吕倍克为例,号码簿上大约有n=250,000项,因为号码簿是按人名的字母顺序排列的,因此最多进行18=log2n次比较就可以找到Bob如果号码簿没排序,则需要从头到尾逐个比较每个名字。Bob可能出现在任一位置,因此平均比较次数是所有项数的二分之一。即使对吕倍克这样规模不大的城市,这也是不现实的(如果Alice本来打电话是想请Bob来吃晚饭,说不定到第二天早上号码还没找到呢)。虽然我们不会严格按二分搜索的步骤查电话号码,即使计算机科学家也不会这么做,但我们都能很方便地查到所要的号码,因为我们知道号码簿内容按字母顺序的。

                                   14.5 常规的电话号码簿

假如我们换个方向,从电话号码查号码所有人,那会怎么样呢?

Alice在电话屏上看到有人用123456这个号码给她打过电话,可她当时没听见。她不记得这个号码,不想立即打回去。她怎么才能知道这是谁呢?

能用的只有这本号码簿,Alice只能浏览其中所有号码,直到能看到123456对于没有其它手段可以利用的人而言,“号码®人名”是单向函数。

不过计算机可以采用聪明的算法(前面的章节中介绍过)对数据对进行排序,因此很容易提供按号码的排序。用按号码排序的号码簿,我们当然可以想通常查号码一样便捷地查到号码拥有人。不过现在我们还是假设只有传统的纸质电话号码簿。

一家好心的电话公司愿意解决Alice的问题,它按姓名字母顺序给每个用户提供号码。例如Alice被分配的号码mA小于Bob的号码mB因为AB前面。如果我们按照这样的号码进行二分搜索,用不了几秒钟便可以查出某个号码的使用者。

采用有序的电话号码丧失了单向性。Bob很关心自己的隐私,因此不喜欢这样的系统。他希望即使公开了电话号码,实际上仍然是“匿名”的,换句话说每个用户号码的排列看上去必须是“无序”的。Bob求助于国际密码协会,协会设计一个秘密的转换函数,解决了这个问

题。假设原来有序系统中 Alice, AndreasAxel… 的号码分别是:

经过转换后的号码则看上去完全“无序”:

 

                14.6 号码有序的电话号码簿以及经转换后的号码簿

协会知道转换函数,能够很容易地从f(m)计算出原来的m,也就很容易查出号码所有者。

在经转换的电话号码簿中,“姓名®号码”是带密钥的单向函数,密钥就是转换函数h。谁都可以查别人的电话号码,但反过来,只有知道密钥的人才能查出号码的拥有者。

安全性与位数

对特定问题,是否有可能确定不存在有效算法可以解?直观上,要证明对象不存在应该比证明存在困难,因为后者只要能给出一个实例即可。

对于寻找快速算法的问题显然也如此,可能的对象有无穷多个。

要彻底打消人们对于密码系统安全性的怀疑,必须证明加密函数的反函数的有效算法不存在。信息科学三十多年来试图提供分析性方法可以证明特定问题的有效算法不存在。虽然取得一些重要成果,但离我们希望的目标还很遥远。

最后我们想让大家对于“大数分解”的难度有些直观的概念。表14.1中给出了分解两个大素数所需要的计算时间的估计值。作为比较,表中也包括几个物理量。

14.1 质因子分解取整的估计值

描述                                        需要的计算时间

使用已知最快的算法

使用全世界所有机器的计算能力

分解为两个256位十进数大约2个月

分解为两个512位十进数大于1000万年

分解为两个1024位十进数大于1018

我们宇宙的生命周期 » 1011

5GHz处理器1年执行的指令周期 » 1.6×1017

全宇宙中的电子数 » 8×1077

十进制100位素数的个数 » 1.8×1097

<think>好的,我现在需要帮助用户解决关于crypt.h头文件的问题。首先,用户提到在编译时遇到了“crypt.h: No such file or directory”的错误,这说明编译器找不到这个头文件。根据我的知识,crypt.h通常与密码加密相关,特别是在Unix/Linux系统中。 接下来,我需要考虑用户可能的环境。用户可能是在Linux系统下进行开发,但不同的发行版可能有不同的包管理方式。例如,Debian/Ubuntu和Fedora/CentOS安装库的方法不同。因此,我应该建议用户根据他们的系统安装相应的开发包。例如,在Ubuntu上可能需要安装libcrypt-dev,而在Fedora上则是libxcrypt-devel。 然后,用户可能需要链接加密库。即使头文件存在,编译时如果没有正确链接库文件,也会出现链接错误。这时候需要检查编译命令是否包含-lcrypt选项。我应该提醒用户添加这个选项,并给出示例命令,比如gcc加上-lcrypt。 另外,用户可能对crypt.h的功能和使用方法感兴趣。需要简要说明该头文件提供的函数,比如crypt()和crypt_r(),并提到它们用于密码加密,但需要注意这些函数的安全性和现代替代方案,比如使用更安全的加密库如OpenSSL或libsodium。 同时,用户可能有不同的使用场景,比如在C程序中调用crypt函数,或者在Python中使用crypt模块。需要分别说明不同语言下的使用方法,并指出Python的crypt模块可能依赖系统库,因此在安装前需要确保开发包已安装。 最后,生成相关问题时要覆盖常见的问题点,比如安装方法、编译选项、函数使用示例以及替代方案。这些问题能够帮助用户进一步解决可能遇到的障碍,或者引导他们了解更安全、更现代的加密方法。 总结一下,我需要分步骤回答用户的问题,包括安装头文件的方法、编译链接选项、功能说明、使用示例和相关注意事项。同时,确保引用提供的参考资料,比如引用[1]、[2]、[3],以增强答案的可信度。</think>### 关于 `crypt.h` 头文件的信息 `crypt.h` 是用于密码加密的C语言头文件,主要提供单向加密函数(如 `crypt()`),常用于Linux/Unix系统的密码验证功能。以下是相关信息的整理: --- #### 1. **安装与配置** - **Linux系统**: 在大多数Linux发行版中,`crypt.h` 属于 `libcrypt-dev` 或 `libxcrypt-dev` 开发包。需通过包管理器安装: - Debian/Ubuntu: ```bash sudo apt-get install libcrypt-dev ``` - Fedora/CentOS: ```bash sudo dnf install libxcrypt-devel ``` - **编译时链接**: 使用 `crypt()` 函数时,需在编译命令中添加 `-lcrypt` 选项: ```bash gcc -o program program.c -lcrypt ``` --- #### 2. **功能与使用** `crypt.h` 定义了以下核心函数: ```c #include <crypt.h> char *crypt(const char *key, const char *salt); ``` - **参数**: - `key`:需加密的明文(如用户输入的密码)。 - `salt`:用于增强加密复杂度的随机字符串。 - **返回值**:加密后的哈希字符串。 **示例代码**: ```c #include <stdio.h> #include <crypt.h> int main() { char *hashed = crypt("password123", "$5$s4ltStr1ng"); printf("Hashed password: %s\n", hashed); return 0; } ``` --- #### 3. **注意事项** - **安全性**: `crypt()` 的默认加密算法(如DES)已过时,建议使用更安全的算法(如SHA-256/512),通过设置 `salt` 前缀指定,例如 `$5$`(SHA-256)或 `$6$`(SHA-512)[^1]。 - **替代方案**: 现代开发中推荐使用更安全的库(如OpenSSL的 `libcrypto` 或 `libsodium`)。 --- #### 4. **跨语言调用** - **Python**: 可通过 `crypt` 模块调用系统库: ```python import crypt hashed = crypt.crypt("password123", "$5$s4ltStr1ng") ``` 需确保系统已安装 `libcrypt` 开发包[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值