首页
社区
课程
招聘
[求助]对于RC2算法,知道若干plain,cipher后能否推出key?
发表于: 2006-5-16 20:49 7381

[求助]对于RC2算法,知道若干plain,cipher后能否推出key?

2006-5-16 20:49
7381
若是能的话最少需要多少对plain,cipher?
哪里能找到源代码?
先谢谢了。

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 370
活跃值: (78)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
2
这个不大可能,因为一般加密算法设计上都考虑了,对算法的差分分析和线性分析,并且有很好的雪崩效应,所以想通过明密文对进行密钥分析是几乎不可能的事情。

附上我写的一个RC2的源代码
rc2.h文件

// RC2.h: interface for the CRC2 class.
// Code By NightFox
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_RC2_H__8EF3A4D2_CB20_47F5_A02B_A10DA08E9155__INCLUDED_)
#define AFX_RC2_H__8EF3A4D2_CB20_47F5_A02B_A10DA08E9155__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/*
*        KEY LENGTH:16 BYTE DEFAULT 1 MIN 128 MAX
*        DATA FORMAT:LITTLE ENDDIAN
*        DATA BLOCK SIZE:8 BYTE
*/

/*
*        RC2 已经测试过了 正常运行 InitUserKey里面的effectiveLen设置为1024
*/

#define DEFAULT_EFFECTIVE_KEYLENGTH 1024
#define MAX_EFFECTIVE_KEYLENGTH 1024

class CRC2  
{
public:
        CRC2();
        virtual ~CRC2();
public:
        void Decipher(const BYTE *inBlock, BYTE *outBlock);
        void Encipher(const BYTE *inBlock,BYTE *outBlock);
        void InitUserKey(const BYTE* key,unsigned int keyLen, unsigned int effectiveLen);
        WORD K[64];
};

#endif // !defined(AFX_RC2_H__8EF3A4D2_CB20_47F5_A02B_A10DA08E9155__INCLUDED_)

rc2.cpp
// RC2.cpp: implementation of the CRC2 class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "RC2.h"

#define rotlFixed16(a,n)        (WORD)((a<<n)|(a>>(16-n)))        //循环左移WORD的代码
#define rotrFixed16(a,n)        (WORD)((a>>n)|(a<<(16-n)))        //循环右移WORD的代码

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CRC2::CRC2()
{

}

CRC2::~CRC2()
{

}

void CRC2::InitUserKey(const BYTE *key, unsigned int keyLen, unsigned int effectiveLen)
{
        static const BYTE PITABLE[256] =
        {
                217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
                198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
                 23,154, 89,245,135,179, 79, 19, 97, 69,109,141,  9,129,125, 50,
                189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130,
                 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220,
                 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38,
                111,191, 14,218, 70,105,  7, 87, 39,242, 29,155,188,148, 67,  3,
                248, 17,199,246,144,239, 62,231,  6,195,213, 47,200,102, 30,215,
                  8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42,
                150, 26,210,113, 90, 21, 73,116, 75,159,208, 94,  4, 24,164,236,
                194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57,
                153,124, 58,133, 35,184,180,122,252,  2, 54, 91, 37, 85,151, 49,
                 45, 93,250,152,227,138,146,174,  5,223, 41, 16,103,108,186,201,
                211,  0,230,207,225,158,168, 44, 99, 22,  1, 63, 88,226,137,169,
                 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
                197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
        };

        BYTE L[128];
        ZeroMemory(L,128);
        memcpy(L,key,keyLen);

        int i;
        for (i=keyLen; i<128; i++)
                L[i] = PITABLE[(L[i-1] + L[i-keyLen]) & 255];

        unsigned int T8 = (effectiveLen+7) / 8;
        BYTE TM = 255 >> ((8-(effectiveLen%8))%8);
        L[128-T8] = PITABLE[L[128-T8] & TM];

        for (i=127-T8; i>=0; i--)
                L[i] = PITABLE[L[i+1] ^ L[i+T8]];

        for (i=0; i<64; i++)
                K[i] = (WORD)L[2*i] + (((WORD)(L[2*i+1])) << 8);
}

void CRC2::Encipher(const BYTE *inBlock, BYTE *outBlock)
{
        WORD R0, R1, R2, R3;
        WORD* p=(WORD*)inBlock;
        R0=p[0];
        R1=p[1];
        R2=p[2];
        R3=p[3];

        for (int i = 0; i < 16; i++)
        {
                R0 += (R1 & ~R3) + (R2 & R3) + K[4*i+0];
                R0 = rotlFixed16(R0, 1);

                R1 += (R2 & ~R0) + (R3 & R0) + K[4*i+1];
                R1 = rotlFixed16(R1, 2);

                R2 += (R3 & ~R1) + (R0 & R1) + K[4*i+2];
                R2 = rotlFixed16(R2, 3);

                R3 += (R0 & ~R2) + (R1 & R2) + K[4*i+3];
                R3 = rotlFixed16(R3, 5);

                if (i == 4 || i == 10)
                {
                        R0 += K[R3 & 63];
                        R1 += K[R0 & 63];
                        R2 += K[R1 & 63];
                        R3 += K[R2 & 63];
                }
        }

        p=(WORD*)outBlock;
        p[0]=R0;
        p[1]=R1;
        p[2]=R2;
        p[3]=R3;
}

void CRC2::Decipher(const BYTE *inBlock, BYTE *outBlock)
{
        WORD R0, R1, R2, R3;
        WORD* p=(WORD*)inBlock;
        R0=p[0];
        R1=p[1];
        R2=p[2];
        R3=p[3];

        for (int i = 15; i >= 0; i--)
        {
                if (i == 4 || i == 10)
                {
                        R3 -= K[R2 & 63];
                        R2 -= K[R1 & 63];
                        R1 -= K[R0 & 63];
                        R0 -= K[R3 & 63];
                }

                R3 = rotrFixed16(R3, 5);
                R3 -= (R0 & ~R2) + (R1 & R2) + K[4*i+3];

                R2 = rotrFixed16(R2, 3);
                R2 -= (R3 & ~R1) + (R0 & R1) + K[4*i+2];

                R1 = rotrFixed16(R1, 2);
                R1 -= (R2 & ~R0) + (R3 & R0) + K[4*i+1];

                R0 = rotrFixed16(R0, 1);
                R0 -= (R1 & ~R3) + (R2 & R3) + K[4*i+0];
        }

        p=(WORD*)outBlock;
        p[0]=R0;
        p[1]=R1;
        p[2]=R2;
        p[3]=R3;
}

调用过程先初始化key,加密过程调用Encipher,解密调用Decipher
2006-5-16 21:28
0
雪    币: 222
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
谢谢。
再问一下:
要是知道KEY为32位呢?能否推出KEY或初始化后的密钥表即你的那个WORD K[64]?
不能用穷举。
2006-5-16 21:40
0
雪    币: 370
活跃值: (78)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
4
最初由 icow 发布
谢谢。
再问一下:
要是知道KEY为32位呢?能否推出KEY或初始化后的密钥表即你的那个WORD K[64]?
不能用穷举。

你这个问题和你上一个问题本质上是一样的,这个不大可能,要是可行的话,这种加密算法也太不安全了。
2006-5-16 21:46
0
雪    币: 222
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
首先非常感谢你的回答!

因为最近研究一个软件的注册算法。其算法大概是:
1。对输入的注册码进行查表变换后与机器码的SHA-1散列值异或得出一个32位值K(算法可逆)
2。以K为key对0xffffffffffffffff进行RC2加密,得到一个64位值,设为E.
3。以K为key对一常数C(八个字节)进行RC2解密算法得到一个64位值,设为F.
4。F与E按位异或,得到八个字节分别设为N1,N2.......N8
5。以K为key对常数C进行RC2加密算法得到一个64位值,设为G.
6。将常数D(四个字节)与G低四个字节按位异或,得到四个字节分别设为N9,N10,N11,N12
7。对N1,N2,......N12一共12个字节进行SHA-1得到160位散列值高M
8。将M与一给定的散列值比较,相等就注册成功。

我已做出注册机(通过穷举)。并且也得到了给定散列值的明文消息(那十二个字节)。 但因为注册码在注册算法中RC算法是作为KEY出现的,如果不可逆如何求出注册码难道只能通过穷举? 我想原作者不可能每次有人申请注册自已就穷举一遍?我自已优化了一下代码,最快穷举完所有可能也得一个多小时。
当然若用多线程会更快。我只是疑惑作者也是穷举出注册码?

该软件的具体见敝文:
http://bbs.pediy.com/showthread.php?s=&threadid=25430
2006-5-16 22:05
0
雪    币: 342
活跃值: (21)
能力值: ( LV12,RANK:730 )
在线值:
发帖
回帖
粉丝
6
作者可以先用N小时把所有可能的KEY穷举一遍记录到表,以后只需要针对任一机器码通过1可逆算法查表立即得到注册码。
2006-5-17 17:32
0
雪    币: 222
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
7
最初由 月中人 发布
作者可以先用N小时把所有可能的KEY穷举一遍记录到表,以后只需要针对任一机器码通过1可逆算法查表立即得到注册码。


这个表太大了。
有0xffffffff种可能。每个机器码存储至少5个字节,表的大小最小也得0xffffffff*5  字节大小。那可是20G的表啊。
2006-5-17 21:15
0
雪    币: 222
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
8
重新分析了一下算法,顿悟!

K为一定值。穷举出一个正确的注册码后就可求出K
注册机就好写了。。。

总结: 开始以为算法很复杂(四次RC2加密,一次RC2解密,两次SHA-1加密),已经够强了。现在看来没什么强度了,只需要一个正确的注册码即可。上述算法八个步骤对写注册机来说只需要第一个步骤就行了。看来还是要多动脑多动手才有进步。。。

谢谢以上各位朋友的帮助
2006-5-17 21:33
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这个总结的很好
2006-5-18 19:25
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
这个总结的很好
2006-5-18 19:43
0
雪    币: 222
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
11
呵呵,小菜的想法,大家不要笑话就行!
2006-5-18 22:15
0
游客
登录 | 注册 方可回帖
返回
//