2.钥扩展算法
SAFER+在密钥扩展中,使用密钥匙扩展数组m_nKeyExpandBox[(m_nChipherLen+1)*m_
nWord/2]和密钥数组m_nKeyBox[m_nChipherLen+1],算法首先将string型密钥m_sEncryptionKey由Unicode字符集转换成ASCII的密钥数组m_nKeyBox(过程不再详述),然后进行密钥扩展数组的构造,在将256位密钥,即32字节赋值到Byte型的数组m_nKeyBox,即赋值范围是m_nKeyBox[0]-m_nKeyBox[31],而m_nKeyBox[]共计33元素,最后一位m_nKeyBox[32]有什么用呢?其实这一位是前面32个元素作异或的结果。接着算法作32轮迭代,在第i轮迭代中,首先需要将密钥数组m_nKeyBox中的元素循环左移三位,即首三位移至末三位,为此只有采取分别左移三位与右移五位后,再作异或运算来达此目的,这里,C#程序与传统的SAFER+ C源代码略有不同,C源代码的处理方式是:
By = lk[j];
Lk[j] = (by << 3) | (by >> 5);
C#编译器在作(by << 3) | (by >> 5)运算时,会自动将运算级别由byte上升至int型,C#的int是32位的,如果不作强制类型转换,是不可能把该表达式的值赋给byte型的lk[j]的,为此需要将左移三位和右移五位的运算先与0xFF做与(&)操作,只取结果的低8位,最后二者的或(|)操作也取低8位,最终作类型强制转换为byte型,这样才能保证编译器的正常运转,代码如下:
temp = m_nKeyBox[j];
m_nKeyBox[j] = (byte)((((temp << 3) & 0xFF) | ((temp >> 5) & 0xFF)) & 0xFF);
在这第i轮的迭代中,若i<16,则m_nKeyExpandBox取值为m_nKeyExpandBox[l + j] = (byte)((m_nKeyBox[m] + m_nExpBox[m_nExpBox[(k + j) & 0xFF]]) & 0xFF);注意到该加法运算是模256的方式,所以通过将结果与0xFF作与(&)运算,从而保证模256的正确性,保证高位为0,而强制类型转换的理由同上述循环移位的解释。若i>=0,则赋值为另一方式,代码如下:
if (i < 16)
{
for (j = 0; j < 16; ++j)
{
m_nKeyExpandBox[l + j] = (byte)((m_nKeyBox[m] + m_nExpBox[m_nExpBox[(k + j) & 0xFF]]) & 0xFF);
m = (m == m_nChipherLen ? 0 : m + 1);
}
}
else
{
for (j=0;j<16;++j)
{
m_nKeyExpandBox[l + j] = (byte)((m_nKeyBox[m] + m_nExpBox[(k + j) & 0xFF]) & 0xFF);
m = (m == m_nChipherLen ? 0 : m + 1);
}
}
3.加密算法
算法首先将string型的明文m_sInClearText置入byte型的字节数组input中,注意到string型使用unicode字符集,所以16位的m_m_sInClearText将转换成32个元素的input,而明文则在input数组的偶数位下标中,如input[0]、input[2],……,input[30]中,(当然也可以使用密钥扩展算法中的方法,即全部使用ASCII码,这样,该数组的范围将为input[0]-input[15])。
然后进行32轮迭代,在第i轮迭代中,采用32*i+j的运算来定位密钥扩展数组n_LocKeyExpandBox的下标,用表达式的运算结果来与0xFF作与(&)操作,从而达到运算结果模256的要求,代码如下:
input[0] = (byte)((m_nExpBox[input[0] ^ n_LocKeyExpandBox[32 * i]] + n_LocKeyExpandBox[32 * i + 16]) & 0xFF);
input[2] = (byte)((m_nLogBox[input[2] + n_LocKeyExpandBox[32 * i + 1]] ^ n_LocKeyExpandBox[32 * i + 17]) & 0xFF);
input[4] = (byte)((m_nLogBox[input[4] + n_LocKeyExpandBox[32 * i + 2]] ^ n_LocKeyExpandBox[32 * i + 18]) & 0xFF);
input[6] = (byte)((m_nExpBox[input[6] ^ n_LocKeyExpandBox[32 * i + 3]] + n_LocKeyExpandBox[32 * i + 19]) & 0xFF);
input[8] = (byte)((m_nExpBox[input[8] ^ n_LocKeyExpandBox[32 * i + 4]] + n_LocKeyExpandBox[32 * i + 20]) & 0xFF);
input[10] = (byte)((m_nLogBox[input[10] + n_LocKeyExpandBox[32 * i + 5]] ^ n_LocKeyExpandBox[32 * i + 21]) & 0xFF);
input[12] = (byte)((m_nLogBox[input[12] + n_LocKeyExpandBox[32 * i + 6]] ^ n_LocKeyExpandBox[32 * i + 22]) & 0xFF);
input[14] = (byte)((m_nExpBox[input[14] ^ n_LocKeyExpandBox[32 * i + 7]] + n_LocKeyExpandBox[32 * i + 23]) & 0xFF);
input[16] = (byte)((m_nExpBox[input[16] ^ n_LocKeyExpandBox[32 * i + 8]] + n_LocKeyExpandBox[32 * i + 24]) & 0xFF);
input[18] = (byte)((m_nLogBox[input[18] + n_LocKeyExpandBox[32 * i + 9]] ^ n_LocKeyExpandBox[32 * i + 25]) & 0xFF);
input[20] = (byte)((m_nLogBox[input[20] + n_LocKeyExpandBox[32 * i + 10]] ^ n_LocKeyExpandBox[32 * i + 26]) & 0xFF);
input[22] = (byte)((m_nExpBox[input[22] ^ n_LocKeyExpandBox[32 * i + 11]] + n_LocKeyExpandBox[32 * i + 27]) & 0xFF);
input[24] = (byte)((m_nExpBox[input[24] ^ n_LocKeyExpandBox[32 * i + 12]] + n_LocKeyExpandBox[32 * i + 28]) & 0xFF);
input[26] = (byte)((m_nLogBox[input[26] + n_LocKeyExpandBox[32 * i + 13]] ^ n_LocKeyExpandBox[32 * i + 29]) & 0xFF);
input[28] = (byte)((m_nLogBox[input[28] + n_LocKeyExpandBox[32 * i + 14]] ^ n_LocKeyExpandBox[32 * i + 30]) & 0xFF);
input[30] = (byte)((m_nExpBox[input[30] ^ n_LocKeyExpandBox[32 * i + 15]] + n_LocKeyExpandBox[32 * i + 31]) & 0xFF);
|