最近应产线的要求,需要我们将meid转换成为pesn来使用。
首先,我们来看下meid,这个东西就是以前我们所说的32bit的ESN的扩展版,因为手机越来越多,32bit的ESN已经不能满足需求了,这就出来了一个meid,meid为56bit,我们可以通过sha1算法将meid转换成为pesn.其中pesn也是32bit,成为伪esn。
总共给过来大概有20000万多个meid,需要我们转换成为pesn,其中涉及到了C的memory和file。实现如下:
#include
#include "memory.h"
using namespace std;
typedef unsigned char byte; /* Unsigned 8 bit value type. */
typedef unsigned short word; /* Unsinged 16 bit value type. */
typedef unsigned long dword; /* Unsigned 32 bit value type. */
typedef unsigned long qword[2];
/* ------------------------------------------------------------ */
/* Constants and definitions for SHA-1 */
/* ------------------------------------------------------------ */
typedef union
{
unsigned long l[16];
unsigned char c[64];
} CHAR64LONG16;
/* Optimizations */
unsigned long rol30( unsigned long value)
{
return (value << 30) | ((value >> 2) & 0x3fffffff);
}
unsigned long rol24( unsigned long value)
{
return (value << 24) | ((value >> 8) & 0x00ffffff);
}
unsigned long rol8( unsigned long value)
{
return (value << 8) | ((value >> 24) & 0x000000ff);
}
unsigned long rol5( unsigned long value)
{
return (value << 5) | ((value >> 27) & 0x0000001f);
}
unsigned long rol1( unsigned long value)
{
return (value << 1) | ((value >> 31) & 0x00000001);
}
/* blk0() and blk() perform the initial expand */
//#if defined(__BIG_ENDIAN)
//#define blk0(block, i) (block->l[i])
//#else
#define blk0(block, i) (block->l[i] = (rol24(block->l[i]) & 0xff00ff00UL) | (rol8(block->l[i]) & 0x00ff00ffUL))
//#endif
#define blk(block, i) (block->l[i & 0x0f] = rol1(block->l[(i + 13) & 0x0f] ^ block->l[(i + 8) & 0x0f] ^ block->l[(i + 2) & 0x0f] ^ block->l[(i + 0) & 0x0f]))
/* R0, R1, R2, R3, R4 are the different operations used in SHA1 */
#define R0(block, work, v, w, x, y, z, i) \
(work[z] += ((work[w]&(work[x]^work[y]))^work[y]) + blk0(block, i) + 0x5a827999UL + rol5(work[v]), work[w] = rol30(work[w]))
#define R1(block, work, v, w, x, y, z, i) \
(work[z] += ((work[w]&(work[x]^work[y]))^work[y]) + blk(block, i) + 0x5a827999UL + rol5(work[v]), work[w] = rol30(work[w]))
#define R2(block, work, v, w, x, y, z, i) \
(work[z] += (work[w]^work[x]^work[y]) + blk(block, i) + 0x6ed9eba1UL + rol5(work[v]), work[w] = rol30(work[w]))
#define R3(block, work, v, w, x, y, z, i) \
(work[z] += (((work[w]|work[x])&work[y])|(work[w]&work[x])) + blk(block, i) + 0x8f1bbcdcUL + rol5(work[v]), work[w] = rol30(work[w]))
#define R4(block, work, v, w, x, y, z, i) \
(work[z] += (work[w]^work[x]^work[y]) + blk(block, i) + 0xca62c1d6UL + rol5(work[v]), work[w] = rol30(work[w]))
/* end of duplicated defines */
#define QW_BYTE(val,idx) \
( \
( (byte*)(val) )[ idx ] \
)
#define MCC_PESN_PREFIX 0x80000000UL /* Pseudo-ESN Prefix */
#define MCC_PESN_PREFIX_MASK 0xFF000000UL /* Pseudo-ESN Prefix mask */
void mcc_meid_create_sha1_digest
(
qword meid, /* Mobile Equipment Identifier */
unsigned long * pmeidhash /* SHA-1 digest */
);
void mcc_sechsharm_sha1_transform
(
unsigned long* iv,
unsigned char* buf
);
/*===========================================================================
FUNCTION MCC_MEID_CREATE_SHA1_DIGEST
DESCRIPTION
This function computes the msg digest (160 bits) using the SHA-1 algorithm.
DEPENDENCIES
RETURN VALUE
TRUE - Success
FALSE - Fail
SIDE EFFECTS
===========================================================================*/
void mcc_meid_create_sha1_digest
(
qword meid, /* Mobile Equipment Identifier */
unsigned long * pmeidhash /* SHA-1 digest */
)
{
unsigned char m[64];
int i; /* loop varaible */
/* Pad the MEID field to form a 512 bit block,
* the padding shall be a 1 followed by all '0's,
* the last 64 bits shall be the binary representation
* of the message length, in this case, 56.
*/
for (i=0; i< 64; i++)
{
m[i] = 0;
}
m[0] = QW_BYTE(meid, 6);
m[1] = QW_BYTE(meid, 5);
m[2] = QW_BYTE(meid, 4);
m[3] = QW_BYTE(meid, 3);
m[4] = QW_BYTE(meid, 2);
m[5] = QW_BYTE(meid, 1);
m[6] = QW_BYTE(meid, 0);
m[7] = 0x80;
m[60] = 0;
m[61] = 0;
m[62] = 0;
m[63] = 0x38;
/* SHA1 initialization constants */
pmeidhash[0] = 0x67452301UL;
pmeidhash[1] = 0xefcdab89UL;
pmeidhash[2] = 0x98badcfeUL;
pmeidhash[3] = 0x10325476UL;
pmeidhash[4] = 0xc3d2e1f0UL;
mcc_sechsharm_sha1_transform(pmeidhash, m );
}
/*===========================================================================
FUNCTION MCC_SECHSHARM_SHA1_TRANSFORM
DESCRIPTION
This function performs the SHA-1 algorithm.
DEPENDENCIES
RETURN VALUE
None
SIDE EFFECTS
===========================================================================*/
void mcc_sechsharm_sha1_transform
(
unsigned long* iv,
unsigned char* buf
)
{
unsigned long bufi[16]; /* internal buffer */
unsigned long work[5]; /* internal work registers */
CHAR64LONG16* block = (CHAR64LONG16*) bufi;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Copy operating buffer to buf */
memcpy( bufi, buf, sizeof( bufi ) );
/* Copy context->iv[] to working vars */
work[0] = iv[0]; /* a */
work[1] = iv[1]; /* b */
work[2] = iv[2]; /* c */
work[3] = iv[3]; /* d */
work[4] = iv[4]; /* e */
/* 4 rounds of 20 operations each. Loop unrolled */
/* Round 1 */
R0( block, work, 0, 1, 2, 3, 4, 0 );
R0( block, work, 4, 0, 1, 2, 3, 1 );
R0( block, work, 3, 4, 0, 1, 2, 2 );
R0( block, work, 2, 3, 4, 0, 1, 3 );
R0( block, work, 1, 2, 3, 4, 0, 4 );
R0( block, work, 0, 1, 2, 3, 4, 5 );
R0( block, work, 4, 0, 1, 2, 3, 6 );
R0( block, work, 3, 4, 0, 1, 2, 7 );
R0( block, work, 2, 3, 4, 0, 1, 8 );
R0( block, work, 1, 2, 3, 4, 0, 9 );
R0( block, work, 0, 1, 2, 3, 4, 10 );
R0( block, work, 4, 0, 1, 2, 3, 11 );
R0( block, work, 3, 4, 0, 1, 2, 12 );
R0( block, work, 2, 3, 4, 0, 1, 13 );
R0( block, work, 1, 2, 3, 4, 0, 14 );
R0( block, work, 0, 1, 2, 3, 4, 15 );
R1( block, work, 4, 0, 1, 2, 3, 16 );
R1( block, work, 3, 4, 0, 1, 2, 17 );
R1( block, work, 2, 3, 4, 0, 1, 18 );
R1( block, work, 1, 2, 3, 4, 0, 19 );
/* Round 2 */
R2( block, work, 0, 1, 2, 3, 4, 20 );
R2( block, work, 4, 0, 1, 2, 3, 21 );
R2( block, work, 3, 4, 0, 1, 2, 22 );
R2( block, work, 2, 3, 4, 0, 1, 23 );
R2( block, work, 1, 2, 3, 4, 0, 24 );
R2( block, work, 0, 1, 2, 3, 4, 25 );
R2( block, work, 4, 0, 1, 2, 3, 26 );
R2( block, work, 3, 4, 0, 1, 2, 27 );
R2( block, work, 2, 3, 4, 0, 1, 28 );
R2( block, work, 1, 2, 3, 4, 0, 29 );
R2( block, work, 0, 1, 2, 3, 4, 30 );
R2( block, work, 4, 0, 1, 2, 3, 31 );
R2( block, work, 3, 4, 0, 1, 2, 32 );
R2( block, work, 2, 3, 4, 0, 1, 33 );
R2( block, work, 1, 2, 3, 4, 0, 34 );
R2( block, work, 0, 1, 2, 3, 4, 35 );
R2( block, work, 4, 0, 1, 2, 3, 36 );
R2( block, work, 3, 4, 0, 1, 2, 37 );
R2( block, work, 2, 3, 4, 0, 1, 38 );
R2( block, work, 1, 2, 3, 4, 0, 39 );
/* Round 3 */
R3( block, work, 0, 1, 2, 3, 4, 40 );
R3( block, work, 4, 0, 1, 2, 3, 41 );
R3( block, work, 3, 4, 0, 1, 2, 42 );
R3( block, work, 2, 3, 4, 0, 1, 43 );
R3( block, work, 1, 2, 3, 4, 0, 44 );
R3( block, work, 0, 1, 2, 3, 4, 45 );
R3( block, work, 4, 0, 1, 2, 3, 46 );
R3( block, work, 3, 4, 0, 1, 2, 47 );
R3( block, work, 2, 3, 4, 0, 1, 48 );
R3( block, work, 1, 2, 3, 4, 0, 49 );
R3( block, work, 0, 1, 2, 3, 4, 50 );
R3( block, work, 4, 0, 1, 2, 3, 51 );
R3( block, work, 3, 4, 0, 1, 2, 52 );
R3( block, work, 2, 3, 4, 0, 1, 53 );
R3( block, work, 1, 2, 3, 4, 0, 54 );
R3( block, work, 0, 1, 2, 3, 4, 55 );
R3( block, work, 4, 0, 1, 2, 3, 56 );
R3( block, work, 3, 4, 0, 1, 2, 57 );
R3( block, work, 2, 3, 4, 0, 1, 58 );
R3( block, work, 1, 2, 3, 4, 0, 59 );
/* Round 4 */
R4( block, work, 0, 1, 2, 3, 4, 60 );
R4( block, work, 4, 0, 1, 2, 3, 61 );
R4( block, work, 3, 4, 0, 1, 2, 62 );
R4( block, work, 2, 3, 4, 0, 1, 63 );
R4( block, work, 1, 2, 3, 4, 0, 64 );
R4( block, work, 0, 1, 2, 3, 4, 65 );
R4( block, work, 4, 0, 1, 2, 3, 66 );
R4( block, work, 3, 4, 0, 1, 2, 67 );
R4( block, work, 2, 3, 4, 0, 1, 68 );
R4( block, work, 1, 2, 3, 4, 0, 69 );
R4( block, work, 0, 1, 2, 3, 4, 70 );
R4( block, work, 4, 0, 1, 2, 3, 71 );
R4( block, work, 3, 4, 0, 1, 2, 72 );
R4( block, work, 2, 3, 4, 0, 1, 73 );
R4( block, work, 1, 2, 3, 4, 0, 74 );
R4( block, work, 0, 1, 2, 3, 4, 75 );
R4( block, work, 4, 0, 1, 2, 3, 76 );
R4( block, work, 3, 4, 0, 1, 2, 77 );
R4( block, work, 2, 3, 4, 0, 1, 78 );
R4( block, work, 1, 2, 3, 4, 0, 79 );
/* Add the working vars back into context.iv[] */
iv[0] += work[0];
iv[1] += work[1];
iv[2] += work[2];
iv[3] += work[3];
iv[4] += work[4];
} /* sechsharm_sha1_transform() */
int main()
{
dword pesn = 0x0UL; /* pseudo-ESN */
unsigned long meidhash[5]; /* MEID SHA-1 digest */
unsigned long meid[2];
unsigned int j;
char str[15];
byte a[16];
int i;
FILE* fpin;
FILE* fpout;
fpin = fopen("a.txt","rt");
fpout = fopen("b.txt","at");
for(j=0; j<28801; j++)
{
fseek(fpin, j*17*sizeof(char), 0);
memset(str, 0, 15*sizeof(char));
fgets(str, 15, fpin);
memset(a, 0, 16*sizeof(byte));
for(i=0; i<14; i++)
{
if(str[i] <= 57)
a[i + 2] = str[i] - 48;
else if(str[i] >= 97 && str[i] <= 102)
a[i + 2] = str[i] -97 + 10;
else if(str[i] >= 65 && str[i] <= 70)
a[i + 2] = str[i] - 65 + 10;
}
meid[0] = (dword)a[8]<<28 | (dword)a[9]<<24 | (dword)a[10]<<20 | (dword)a[11]<<16 | (dword)a[12]<<12 | (dword)a[13]<<8 | (dword)a[14]<<4 | (dword)a[15];
meid[1] = (dword)a[0]<<28 | (dword)a[1]<<24 | (dword)a[2]<<20 | (dword)a[3]<<16 | (dword)a[4]<<12 | (dword)a[5]<<8 | (dword)a[6]<<4 | (dword)a[7];
/*
meid[0] = 0x652983B;
meid[1] = 0xa10000;
*/
mcc_meid_create_sha1_digest(meid, meidhash);
/* SHA-1 digest(hash) was successfully created */
/* the p-ESN is in the lowest 24 bits of meidhash[4] */
pesn = (meidhash[4] & ~MCC_PESN_PREFIX_MASK) | (MCC_PESN_PREFIX);
fprintf(fpout, "%x\n", pesn);
}
fclose(fpin);
fclose(fpout);
return 0;
}
我们定义了2个文件,一个为输入文件,一个为输出文件,输入文件里面保存的是需要转换的meid,输出文件中保存转换完后的pesn。sha1的算法我们就不具体的说了,主要说下如何实现读写文件。
大体的思路应该是这样的:首先,我们从input.txt中读入我们需要的meid,并以char的形式保存到一个数组中,这里我们定义的数组里面保存14个元素,因为保存的是16进制,总共56位。接下来是将数组元素转换成为对应的值,这里有一点需要注意,meid里面的字符串有ABCDEF和abcdef以及0-9之分,而16进制的A和a所代表的值都是一样的,在转换的时候需要考虑到这点。将数组元素由char转换成为8位无符号整数,接下来要做的是将每个数组元素中的低4位取出来放到事先定义好的unsigned long的数组中,作为一个值,这个值就是我们所需要转换的meid的一部分。完成meid数组的初始化后,我们就能利用sha1算法来求pesn了,求出的pesn是一个整数值,我们需要使用fprintf()按照16进制的格式来输出。
注意:
1.fseek函数的使用:我们用它来改变文件指针的位置,由于我们是从txt文件中读值,而不是二进制文件,因此我们需要注意将换行符或者其他与meid无关的符号所代表的二进制去掉,也就是说在我们从input.txt中读取meid的时候,要注意meid间的符号不能一起读到数组里面来,而且在改变文件指针位置的时候,要把符号位所占的字节数加上,这也就是上面为什么是17而不是15了,因为在meid间有2个字节的间隔。
2.从char转换为byte,这里我们采用的是一种比较老的办法,将char中的每个元素减掉字符'0'的ASCII值48,当然这只是针对十进制0-9来说的,由于我们的input.txt里面的meid都是十六进制,还存在ABCDEF,abcdef大小写的区分,这里的a应该表示的是10,于是我们在转换的时候,便需要进行判断是0-9还是大写字母,还是小写字母,分别减掉字符'0','A','a'的ASCII值,这样就得出了我们所需要的byte数组。
3.从byte数组向meid的转换,byte数组中总共有16个元素,而且数组中的每个元素均不大于0x0F,我们需要将byte数组中的前8个元素转换成为unsigned long的meid数组的第二个元素,需要将byte数组中的后8个元素转换成为meid数组中的第一个元素,现在我们需要考虑一下,8个byte类型的数组元素总共是占了64位,而meid的一个元素只是占了32位,我们需要将byte类型数组中的每个元素的低4位取出来,然后放到对应的meid元素里面。这里采用了移位或的办法。