标题: RSASSA-PSS/EMSA-PSS签名方案简介 https://scz.617.cn/misc/201610311241.txt 历史上RSA签名实现出现过很多漏洞,有相当一部分是针对PKCS#1 v1.5的。后来出了 PKCS#1 v2.1,对PKCS#1 v1.5提出一些改进,参看RFC 3447。 -------------------------------------------------------------------------- Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1 - [2003-02] http://www.ietf.org/rfc/rfc3447.txt -------------------------------------------------------------------------- 除了针对PKCS#1 v1.5的改进,RFC 3447另外描述了一种RSASSA-PSS/EMSA-PSS签名方 案。 大家都知道,RFC很是佶屈聱牙,从实用主义角度出发,我提供个不严谨的但很容易 为程序员所理解的意译版。 参看RFC 3447的图2: +-----------+ | M | +-----------+ | V Hash | V +--------+----------+----------+ M' = |Padding1| mHash | salt | +--------+----------+----------+ | +--------+----+ V DB = |Padding2|salt| Hash +--------+----+ | | | V | +--+ xor <--- MGF <---| |bc| | | +--+ | | | V V V +-------------------+----------+--+ EM = | maskedDB |maskedseed|bc| +-------------------+----------+--+ 原图中有一处大错,DB的第二部分应该是salt,而不是原图中的maskedseed。 下面是一组面向逆向工程人员的通俗解释: -------------------------------------------------------------------------- M 待签名的数据 Hash SHA-1 mHash SHA1( M ) Padding1 00 00 00 00 00 00 00 00 8个0x00 salt 0x14字节的随机字节流 maskedseed SHA1( Padding1 + mHash + salt ) MGF( maskedseed ) SHA1( maskedseed + 00 00 00 00 ) + SHA1( maskedseed + 00 00 00 01 ) + SHA1( maskedseed + 00 00 00 02 ) + ... 通过递增4字节counter(big-endian序),可以得到任意长的字节流,但我们只需 要前0x6b字节,即counter只需[0,5],最后一次还得截断 Padding2 00 00 ... 00 01 0x56个0x00以及1个0x01,共长0x57字节 DB Padding2 + salt 共长0x6b字节 maskedDB DB xor MGF( maskedseed ) 将DB与MGF()的输出进行异或,得到0x6b字节的maskedDB 将maskedDB的最高位清零,这一步可以确保后面的RSA算法成立 EM maskedDB + maskedseed + 0xbc 共长0x80字节,结尾的0xbc是识别RSASSA-PSS/EMSA-PSS方案的特征 S EM^d mod n 用私钥(n,d)对EM加密得到S -------------------------------------------------------------------------- 验证签名时,看到的是256字节的"M + S"。 简单说一下签名验证过程: -------------------------------------------------------------------------- . EM = S^e mod n . 通过EM得到maskedDB、maskedseed . DB = maskedDB xor MGF( maskedseed ) . 通过DB得到salt . 通过M得到mHash . Padding1是已知的固定值 . M' = Padding1 + mHash + salt . 计算SHA1(M') . 比较SHA1(M')与maskedseed,如果相等,签名验证通过 -------------------------------------------------------------------------- 中间其实有很多长度检查,还有对DB中Padding2的检查,上面说的是主要部分。 下面是一组验证集,便于产生感性认识: M 00000000 CC 89 75 FC EB 0E 33 C0 40 C3 8B 65 E8 C7 45 FC 00000010 FE FF FF FF E8 74 D1 F8 FF C3 90 90 90 90 90 8B 00000020 FF 55 8B EC 83 EC 10 80 3D EC 02 FE 7F 00 74 11 00000030 8B 45 0C 81 60 68 FF FE FF FD 33 C0 E9 75 01 00 00000040 00 80 7D 10 00 56 57 8B 7D 08 74 57 0F B7 0F 8B 00000050 47 04 0F B7 D1 03 C2 85 D2 74 0F 8D 70 FE 66 83 00000060 3E 5C 74 06 4A 4A 8B C6 75 F1 89 45 FC 68 EC 32 00000070 05 77 8D 45 F0 2B CA 50 66 89 4D F8 E8 13 D4 F8 mHash = SHA1( M ) 00000000 C8 83 16 4A 41 1F 09 A4 BF 67 71 BB 4B BA 43 DD 00000010 31 95 7A 39 salt 00000000 6F FD E4 30 7E 8F AA 9B 4D 8C A2 08 5A B2 D2 0C 00000010 5A B5 31 83 M' = Padding1 + mHash + salt 00000000 00 00 00 00 00 00 00 00 C8 83 16 4A 41 1F 09 A4 00000010 BF 67 71 BB 4B BA 43 DD 31 95 7A 39 6F FD E4 30 00000020 7E 8F AA 9B 4D 8C A2 08 5A B2 D2 0C 5A B5 31 83 maskedseed = SHA1( M' ) 00000000 65 19 FB 53 F2 88 42 10 0F 66 EA E6 E8 3D 59 D6 00000010 F7 FC A4 A5 MGF( maskedseed ) 00000000 FD 9E B1 35 E4 0D 20 38 A0 1F 3B F9 DD 01 1A D2 00000010 D6 11 92 1A DC E6 9B 61 20 78 16 DD CE 58 A9 6D 00000020 00 7F 8D 8C A4 F2 44 AC C1 75 25 59 0D 0E 0E DA 00000030 BA B2 0F F4 4B 17 9B DA CB 83 92 44 2C 49 48 79 00000040 9D 56 55 F9 E5 93 07 89 56 FB 62 F4 E8 77 F6 4E 00000050 6E F0 2D 55 00 E9 C5 27 B6 0D C1 11 4C EF 94 D7 00000060 AD 7F B0 0B 62 70 6F 77 DA 8B B8 DB = Padding2 + salt 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000050 00 00 00 00 00 00 01 6F FD E4 30 7E 8F AA 9B 4D 00000060 8C A2 08 5A B2 D2 0C 5A B5 31 83 maskedDB = DB xor MGF( maskedseed ) 00000000 7D 9E B1 35 E4 0D 20 38 A0 1F 3B F9 DD 01 1A D2 00000010 D6 11 92 1A DC E6 9B 61 20 78 16 DD CE 58 A9 6D 00000020 00 7F 8D 8C A4 F2 44 AC C1 75 25 59 0D 0E 0E DA 00000030 BA B2 0F F4 4B 17 9B DA CB 83 92 44 2C 49 48 79 00000040 9D 56 55 F9 E5 93 07 89 56 FB 62 F4 E8 77 F6 4E 00000050 6E F0 2D 55 00 E9 C4 48 4B E9 F1 6F C3 45 0F 9A 00000060 21 DD B8 51 D0 A2 63 2D 6F BA 3B EM = maskedDB + maskedseed + 0xbc 00000000 7D 9E B1 35 E4 0D 20 38 A0 1F 3B F9 DD 01 1A D2 00000010 D6 11 92 1A DC E6 9B 61 20 78 16 DD CE 58 A9 6D 00000020 00 7F 8D 8C A4 F2 44 AC C1 75 25 59 0D 0E 0E DA 00000030 BA B2 0F F4 4B 17 9B DA CB 83 92 44 2C 49 48 79 00000040 9D 56 55 F9 E5 93 07 89 56 FB 62 F4 E8 77 F6 4E 00000050 6E F0 2D 55 00 E9 C4 48 4B E9 F1 6F C3 45 0F 9A 00000060 21 DD B8 51 D0 A2 63 2D 6F BA 3B 65 19 FB 53 F2 00000070 88 42 10 0F 66 EA E6 E8 3D 59 D6 F7 FC A4 A5 BC n 00000000 C1 B4 9E 42 AC 4A CE 91 CC 3D 3A AC D5 30 0C 69 00000010 2B A6 D5 07 E1 1C 30 14 1D 79 0F 1A 37 D1 D0 F3 00000020 24 A4 F0 DA 37 5D 28 4F 12 A3 33 BA C6 6C A5 46 00000030 72 B9 69 32 91 91 4D D9 0B BC 22 ED 80 1E 5B CA 00000040 59 D4 22 C9 55 27 41 46 5C 5E CA DF 07 FB 61 74 00000050 4F A7 15 85 FB 8B 4A 11 C7 56 78 A3 34 9F 33 CE 00000060 B7 02 C9 E9 52 00 FF 99 9A 82 BB AE 8D 46 66 02 00000070 50 1B ED D5 72 DC 81 FC C9 23 43 16 17 76 72 23 d 00000000 AF 70 84 4A 44 BB F8 3D EA EA A5 E2 F5 AF 6F FE 00000010 2D 30 0C 0F F7 DD CC D9 DB 1B D3 06 DE F9 A4 B3 00000020 23 44 54 74 7F E2 5A E8 CB 2B 8F 65 A1 E3 B3 09 00000030 8C 4C CB AF A6 52 21 5C EC 98 F8 55 7D 4D 81 B9 00000040 BD 36 47 4A 83 89 AE 37 C3 80 2D 01 FF FA 83 D3 00000050 5D E4 F0 75 3F 53 B1 B5 80 33 E8 06 86 7A 8F 28 00000060 A3 E4 5E 8C 0E 66 34 E7 56 D6 00 53 91 AD 00 40 00000070 E3 A6 76 FB 18 0C 08 0B 6E 89 44 83 FA D8 5D D9 e 00000000 00 01 00 01 S = EM^d mod n 00000000 25 80 DA C1 2A C3 70 34 13 2B F3 AC 19 07 75 F6 00000010 70 13 C4 2B 59 EF BC E8 11 95 AE 90 D8 93 8D 19 00000020 B8 BE 04 E5 2F E0 CB 93 51 2B 85 E8 01 5D F0 64 00000030 6F 51 86 24 31 AD 71 76 57 79 EF 31 9A 2D 3D 0D 00000040 8A 68 EE 32 68 09 A4 9A C6 FA 87 6F 33 B1 D2 D0 00000050 D7 4C 86 21 94 F5 5B 4C 69 56 A8 FF AA 13 09 2D 00000060 13 A7 5F 2F C7 24 5C A4 97 7F 9B 30 E4 CD 67 B0 00000070 75 A6 AE 2C 5F 8D 54 D0 3A 5A B2 36 D0 86 12 AC M + S 00000000 CC 89 75 FC EB 0E 33 C0 40 C3 8B 65 E8 C7 45 FC 00000010 FE FF FF FF E8 74 D1 F8 FF C3 90 90 90 90 90 8B 00000020 FF 55 8B EC 83 EC 10 80 3D EC 02 FE 7F 00 74 11 00000030 8B 45 0C 81 60 68 FF FE FF FD 33 C0 E9 75 01 00 00000040 00 80 7D 10 00 56 57 8B 7D 08 74 57 0F B7 0F 8B 00000050 47 04 0F B7 D1 03 C2 85 D2 74 0F 8D 70 FE 66 83 00000060 3E 5C 74 06 4A 4A 8B C6 75 F1 89 45 FC 68 EC 32 00000070 05 77 8D 45 F0 2B CA 50 66 89 4D F8 E8 13 D4 F8 00000080 25 80 DA C1 2A C3 70 34 13 2B F3 AC 19 07 75 F6 00000090 70 13 C4 2B 59 EF BC E8 11 95 AE 90 D8 93 8D 19 000000A0 B8 BE 04 E5 2F E0 CB 93 51 2B 85 E8 01 5D F0 64 000000B0 6F 51 86 24 31 AD 71 76 57 79 EF 31 9A 2D 3D 0D 000000C0 8A 68 EE 32 68 09 A4 9A C6 FA 87 6F 33 B1 D2 D0 000000D0 D7 4C 86 21 94 F5 5B 4C 69 56 A8 FF AA 13 09 2D 000000E0 13 A7 5F 2F C7 24 5C A4 97 7F 9B 30 E4 CD 67 B0 000000F0 75 A6 AE 2C 5F 8D 54 D0 3A 5A B2 36 D0 86 12 AC 再次强调,EM结尾的0xbc是识别RSASSA-PSS/EMSA-PSS方案的特征。切记将maskedDB 的最高位清零。