A5/1加密算法用于GSM中的数据机密性加密。该算法使用三个线性反馈位移寄存器,记为为X、Y和Z。其中X(x0, x1, …, x18)寄存器有19位,Y寄存器22位,Z寄存器23位。以下不讲原理,只讲密钥流生成算法。
一下用C++简单实现了一下,比较简单就不多讲了。
#include
#include
#include
#define _for(i,a,b) for(int i=(a); i<(b); ++i)
#define setbit(x,y) x|=(1<
#define clrbit(x,y) x&=~(1<
#define reversebit(x,y) x^=(1<
#define getbit(x,y) (x&=(1<
using namespace std;
typedef unsigned char uc;
bool x[19] = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1};
bool y[22] = {1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1};
bool z[23] = {1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0};
int maj(bool x, bool y, bool z) {
return x + y + z >= 2;
}
void X(bool x[]) {
bool temp = x[13] ^ x[16] ^ x[17] ^ x[18];
for(int i = 18; i >= 1; i--) {
x[i] = x[i-1];
}
x[0] = temp;
}
void Y(bool y[]) {
bool temp = y[20] ^ y[21];
for(int i = 21; i >= 1; i--) {
y[i] = y[i-1];
}
y[0] = temp;
}
void Z(bool z[]) {
bool temp = z[7] ^ z[20] ^ z[21] ^ z[22];
for(int i = 22; i >= 1; i--) {
z[i] = z[i-1];
}
z[0] = temp;
}
uc* generateSecretKeyStream(int n) {
bool temp[8];
uc* secretKeyStream = (uc*)malloc(n/8 + 1);
int cnt = 0, cnt1 = 0;
_for(i, 0, n) {
bool m = maj(x[8], y[10], z[10]);
if(x[8] == m) {
X(x);
}
if(y[10] == m) {
Y(y);
}
if(z[10] == m) {
Z(z);
}
bool s = x[18] ^ y[21] ^ z[22];
temp[cnt++] = s;
if(cnt == 8) {
_for(j, 0, cnt) {
if(temp[j] == 0) {
clrbit(secretKeyStream[cnt1], j);
} else {
setbit(secretKeyStream[cnt1], j);
}
}
cnt1++;
cnt = 0;
}
}
_for(j, 0, cnt) {
if(temp[j] == 0) {
clrbit(secretKeyStream[cnt1], j);
} else {
setbit(secretKeyStream[cnt1], j);
}
}
return secretKeyStream;
}
int getFileSize(FILE *fp) {
fseek(fp, 0L, SEEK_END);
int size = ftell(fp);
fseek(fp, 0L, 0);
return size;
}
uc* readFromFile(FILE *fp, int size) {
uc *buffer = (uc *)malloc(sizeof(uc) * size);
fread(buffer, size, 1, fp);
return buffer;
}
void encrypt(char* fileName) {
FILE* fp = fopen(fileName, "rb");
int fileSize = getFileSize(fp);
uc *buffer = readFromFile(fp, fileSize);
uc* secretKeyStream = generateSecretKeyStream(fileSize * 8);
_for(i, 0, fileSize) {
buffer[i] ^= secretKeyStream[i];
}
FILE* fp1 = fopen("secret.a51", "wb");
fwrite(buffer, fileSize, 1, fp1);
_for(i, 0, fileSize) {
buffer[i] ^= secretKeyStream[i];
}
FILE* fp2 = fopen("_secret.a51", "wb");
fwrite(buffer, fileSize, 1, fp2);
fclose(fp);
fclose(fp1);
fclose(fp2);
free(buffer);
}
int main(int argc, char const **argv) {
char fileName[50] = "lenna.bmp";
encrypt(fileName);
return 0;
}