0、写在前面
windows和office的序列号就是在最终换算之后,通过base24编码转换成为可显示字符串的。写这个系列的目的就是做类似的东东。
1、编码原理
在base32的那篇文章中已经比较详细的说明了,这里只指出与原理相比较,base24是一个非常奇怪的方案,因为用4个bits作为分码段,只能用到16个,另外8个编码字符用不到,而采用5个bits作为分码段,又少8个字符。这就是之前写了个base32的原因。
后来想明白了这个问题,还是4个bits一组,然后在通过另外一种方式把24个字符都用上不就行了,我采用的是比较愚蠢的方式,按照位置取8的余数,再加上编码值换算即可。总之样子上已经没啥区别了。
先申明,我并不知道ms采用的base24的具体的方式是什么,因为和我描述的不同,因为据说它是将114bit编码成为200个bits(25个bytes),我说的方法显然做不到。目前就到这个地步吧,有空再想想。
2、源代码
只把encoding和decoding的两个函数贴出来,其他的都雷同。
public new static string encode(byte[] abdata)
{
int32 dwloop = 0,dwcharindex = 0,dwcharcount = 0,dwrem = 0;
char[] acpart = null;
stringbuilder sboutput = null;
if (abdata == null || m_acbasemap == null || m_acbasemap.length < m_dwmaplength)
return null;
try
{
dwcharcount = abdata.length * 2;
sboutput = new stringbuilder(dwcharcount);
acpart = new char[2];
}
catch (exception e)
{
trace.writeline("clsbase24.encode: initialize buffer failed! " + e.message);
}
if (acpart == null || sboutput == null)
return null;
for(dwloop = 0;dwloop < abdata.length;dwloop++)
{
array.clear(acpart,0,acpart.length);
// one byte will split to two characters
math.divrem(dwloop,9,out dwrem);
dwcharindex = abdata[dwloop] >> 4 + dwrem;
acpart[0] = m_acbasemap[dwcharindex];
dwcharindex = (abdata[dwloop] & 0x0f) + dwrem;
acpart[0] = m_acbasemap[dwcharindex];
sboutput.append(acpart,0,acpart.length);
}
return sboutput.tostring();
}
public new static byte[] decode(string sdata)
{
int32 dwloop = 0,dwlength = 0,dwrem = 0;
int32[] dwcharindex = null;
byte[] aboutput = null;
char[] acinput = null;
if (sdata == null || sdata == string.empty)
return null;
acinput = sdata.tochararray();
if (acinput == null)
return null;
try
{
dwlength = acinput.length / 2;
aboutput = new byte[dwlength];
dwcharindex = new int32[2];
}
catch (exception e)
{
trace.writeline("clsbase24.decode: initialize buffer failed! " + e.message);
}
if (acinput == null)
return null;
dwlength = 0;
for (dwloop = 0;dwloop < acinput.length;dwloop += 2)
{
array.clear(dwcharindex,0,dwcharindex.length);
// two character can merage one byte
math.divrem(dwloop / 2,9,out dwrem);
switch (acinput.length – dwloop)
{
case 1:
dwcharindex[0] = getcharindex(acinput[dwloop]) – dwrem;
aboutput[dwlength] = (byte) (dwcharindex[0] << 4);
break;
default:
dwcharindex[0] = getcharindex(acinput[dwloop]) – dwrem;
dwcharindex[1] = getcharindex(acinput[dwloop + 1]) – dwrem;
aboutput[dwlength] = (byte) (dwcharindex[0] << 4 + dwcharindex[1]);
break;
}
dwlength++;
}
return aboutput;
}
