手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆

Base64转换:AQAB=65537,你知道为什么吗?[转]

首页 > Javascript >

base64 encoder

原文来自博客园:http://www.cnblogs.com/midea0978/archive/2007/05/22/755826.html

作者为:在路上

先贴上BASE64的算法介绍:http://popscanner.icpcn.com/download/base64.doc,这是DOC文档,可以下载一看。

什么是Base64?

按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列 的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)

为什么要使用Base64?

在设计这个编码的时候,我想设计人员最主要考虑了3个问题:
1.是否加密?
2.加密算法复杂程度和效率
3.如何处理传输?

    加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是“防君子不防小人”。即达到一眼望去完全看不出内容即可。
基 于这个目的加密算法的复杂程度和效率也就不能太大和太低。和上一个理由类似,MIME协议等用于发送Email的协议解决的是如何收发Email,而并不 是如何安全的收发Email。因此算法的复杂程度要小,效率要高,否则因为发送Email而大量占用资源,路就有点走歪了。

    但 是,如果是基于以上两点,那么我们使用最简单的恺撒法即可,为什么Base64看起来要比恺撒法复杂呢?这是因为在Email的传送过程中,由于历史原 因,Email只被允许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通 过有“历史问题”的网关时就可能会出现问题。网关可能会把最高位置为0!很明显,问题就这样产生了!因此,为了能够正常的传送Email,这个问题就必须 考虑!所以,单单靠改变字母的位置的恺撒之类的方案也就不行了。关于这一点可以参考RFC2046。
基于以上的一些主要原因产生了Base64编码。 


 

在路上作者的原文为:

       在RSA加密算法中,RSA公钥的public exponent通常都是65537,用base64来表示就是AQAB,这个转换是怎么得来的呢?
通常的base64算法是实现byte[]与base64字符串之间的转换,如果你习惯下面的转换方式,那就错了:

Console.WriteLine(Convert.ToBase64String(Encoding.Default.GetBytes("65537")));

输出的结果:NjU1Mzc=,并不是AQAB。
那么对于数字转换为base64应该怎么转换呢?首先来回顾一下base64算法原理:

1、算法原理
Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。
具体转化形式如下图:

字符串 "张3"
byte[] 110101 011100 010100 110011
添加前缀00, byte[] 00110101 00011100 00010100 00110011
十进制 53    28 20 51
转码 1 c U z

可以这么考虑:把8位的字节连成一串110101011100010100110011
然后每次顺序选6个出来之后再把这6二进制数前面再添加两个0,就成了一个新的字节。之后再选出6个来,再添加0,依此类推,直到24个二进制数全部被选完。

那么,根据上面的对照表计算出字符串“张3”的base64编码就是"1cUz"
2、转码对照表

Value Encoding  Value Encoding  Value Encoding  Value Encoding
         
0 A            17 R            34 i            51 z
         
1 B            18 S            35 j            52 0
         
2 C            19 T            36 k            53 1
         
3 D            20 U            37 l            54 2
         
4 E            21 V            38 m            55 3
         
5 F            22 W            39 n            56 4
         
6 G            23 X            40 o            57 5
         
7 H            24 Y            41 p            58 6
         
8 I             25 Z            42 q            59 7
         
9 J             26 a            43 r            60 8
        
10 K            27 b            44 s            61 9
        
11 L            28 c            45 t            62 +
        
12 M            29 d            46 u            63 /
        
13 N            30 e            47 v
        
14 O            31 f            48 w         (pad) =
        
15 P            32 g            49 x
        
16 Q            33 h            50 y

3、AQAB与65537
根据上面的原理,实际上65537作为数字就不能直接转换字符串再转换为base64,这样只会得出错误的结果,应该直接将65537转换为2进制
Step 1:              1 0000 0000 0000 0001
由于转换需要3个8字节的数据,需要在左边加上前导0,结果就是
Step 2:0000 0001 0000 0000 0000 0001
然后依次取6位,加上00,变成下面的一窜数据
Step 3:0000 0000 0001 0000 0000 0000 0000 0001
每8转换为10进制
Step 4:0  16  0  1
对照转码表
Step 5:AQAB
这就是为什么AQAB=65537,按照上面的原理我们就可以将RSA加密的密钥大质数转换为byte[]或者base64字符串存储了,.net中就是按照base64格式存储的。
4、代码实现
如何用代码来实现上面的转换呢,在.net中有一个类BitConverter可以实现int32=>byte[]的转换,但是转换后高低位的存储位置颠倒了,需要转换过来
例如数字65520=1111 1111 1111 0000=〉BitConverter.GetBytes=〉byte[]={240,255,0,0}
实际我们需要转换为byte[]={0,0,255,240},接下来用Convert.ToBase64String就可以了,下面是演示代码[代码不具有通用性转换性,仅演示]:

C#代码
  1. public static void demo(){  
  2.         byte[] bits=BitConverter.GetBytes(65537);  
  3.         byte[] newbits=new byte[bits.Length-1]; //避免产生padding位,去掉高位0,仅取3位  
  4.         for(int i=0;i<newbits.Length;i++){  
  5.             newbits[i]=bits[bits.Length-2-i];//newbits[0]=bits[2],依次  
  6.         }  
  7.         String s=Convert.ToBase64String(newbits);  
  8.         Console.WriteLine("Base64="+s);  
  9.         newbits=Convert.FromBase64String(s);  
  10.         for(int i=0;i<newbits.Length;i++){  
  11.             bits[bits.Length-2-i]=newbits[i];//newbits[0]=bits[2],依次  
  12.         }  
  13.         bits[3]=0;//高位补0  
  14.         Console.WriteLine("Num="+BitConverter.ToInt32(bits,0));  
  15.   
  16.     }  

后来看到有人回复;

C#代码
  1. 字节顺序取决于特定的计算机结构,所以不应该假定程序总运行在little-endian字节顺序的环境中:  
  2. byte[] bits=BitConverter.GetBytes((int)65537);  
  3. if(BitConverter.IsLittleEndian) Array.Reverse(bits);  
  4. int ofs = 0;  
  5. while(bits[ofs]==0 && ofs < bits.Length) ofs++;  
  6. String s=Convert.ToBase64String(bits,ofs,bits.Length - ofs);  
  7. //Write s  
  8. byte[] intBytes = new byte[4];  
  9. bits = Convert.FromBase64String(s);  
  10. bits.CopyTo(intBytes,intBytes.Length-bits.Length);  
  11. if(BitConverter.IsLittleEndian) Array.Reverse(intBytes);  
  12. int num = BitConverter.ToInt32(intBytes,0);  
  13. //Write num   




本站采用创作共享版权协议, 要求署名、非商业和保持一致. 本站欢迎任何非商业应用的转载, 但须注明出自"膘叔", 保留原始链接, 此外还必须标注原文标题和链接.

Tags: base64, 算法

« 上一篇 | 下一篇 »

只显示10条记录相关文章

MYSQL官方的文章:几种无限分类的算法…… (浏览: 17691, 评论: 0)
Kmeans算法 (浏览: 16774, 评论: 0)
常用JS代码 (浏览: 15867, 评论: 0)
集体智慧编程笔记(一):相似度算法 (浏览: 14575, 评论: 1)
转:经典算法 (浏览: 13792, 评论: 0)

发表评论

评论内容 (必填):