801 WORKPLACE

追寻梦想,自由生活

BlogJava 首页 新随笔 联系 聚合 管理
  10 Posts :: 1 Stories :: 1 Comments :: 0 Trackbacks
最初是下载了一个写好了的Java版SHA1,代码如下:

来源:http://blog.csdn.net/zyg158/archive/2007/06/26/1667531.aspx

  1public class SHA1 {
  2    private final int[] abcde = {
  3            0x674523010xefcdab890x98badcfe0x103254760xc3d2e1f0
  4        }
;
  5    // 摘要数据存储数组
  6    private int[] digestInt = new int[5];
  7    // 计算过程中的临时数据存储数组
  8    private int[] tmpData = new int[80];
  9    // 计算sha-1摘要
 10    private int process_input_bytes(byte[] bytedata) {
 11        // 初试化常量
 12        System.arraycopy(abcde, 0, digestInt, 0, abcde.length);
 13        // 格式化输入字节数组,补10及长度数据
 14        byte[] newbyte = byteArrayFormatData(bytedata);
 15        // 获取数据摘要计算的数据单元个数
 16        int MCount = newbyte.length / 64;
 17        // 循环对每个数据单元进行摘要计算
 18        for (int pos = 0; pos < MCount; pos++{
 19            // 将每个单元的数据转换成16个整型数据,并保存到tmpData的前16个数组元素中
 20            for (int j = 0; j < 16; j++{
 21                tmpData[j] = byteArrayToInt(newbyte, (pos * 64+ (j * 4));
 22            }

 23            // 摘要计算函数
 24            encrypt();
 25        }

 26        return 20;
 27    }

 28    // 格式化输入字节数组格式
 29    private byte[] byteArrayFormatData(byte[] bytedata) {
 30        // 补0数量
 31        int zeros = 0;
 32        // 补位后总位数
 33        int size = 0;
 34        // 原始数据长度
 35        int n = bytedata.length;
 36        // 模64后的剩余位数
 37        int m = n % 64;
 38        // 计算添加0的个数以及添加10后的总长度
 39        if (m < 56{
 40            zeros = 55 - m;
 41            size = n - m + 64;
 42        }
 else if (m == 56{
 43            zeros = 63;
 44            size = n + 8 + 64;
 45        }
 else {
 46            zeros = 63 - m + 56;
 47            size = (n + 64- m + 64;
 48        }

 49        // 补位后生成的新数组内容
 50        byte[] newbyte = new byte[size];
 51        // 复制数组的前面部分
 52        System.arraycopy(bytedata, 0, newbyte, 0, n);
 53        // 获得数组Append数据元素的位置
 54        int l = n;
 55        // 补1操作
 56        newbyte[l++= (byte0x80;
 57        // 补0操作
 58        for (int i = 0; i < zeros; i++{
 59            newbyte[l++= (byte0x00;
 60        }

 61        // 计算数据长度,补数据长度位共8字节,长整型
 62        long N = (long) n * 8;
 63        byte h8 = (byte) (N & 0xFF);
 64        byte h7 = (byte) ((N >> 8& 0xFF);
 65        byte h6 = (byte) ((N >> 16& 0xFF);
 66        byte h5 = (byte) ((N >> 24& 0xFF);
 67        byte h4 = (byte) ((N >> 32& 0xFF);
 68        byte h3 = (byte) ((N >> 40& 0xFF);
 69        byte h2 = (byte) ((N >> 48& 0xFF);
 70        byte h1 = (byte) (N >> 56);
 71        newbyte[l++= h1;
 72        newbyte[l++= h2;
 73        newbyte[l++= h3;
 74        newbyte[l++= h4;
 75        newbyte[l++= h5;
 76        newbyte[l++= h6;
 77        newbyte[l++= h7;
 78        newbyte[l++= h8;
 79        return newbyte;
 80    }

 81    private int f1(int x, int y, int z) {
 82        return (x & y) | (~& z);
 83    }

 84    private int f2(int x, int y, int z) {
 85        return x ^ y ^ z;
 86    }

 87    private int f3(int x, int y, int z) {
 88        return (x & y) | (x & z) | (y & z);
 89    }

 90    private int f4(int x, int y) {
 91        return (x << y) | x >>> (32 - y);
 92    }

 93    // 单元摘要计算函数
 94    private void encrypt() {
 95        for (int i = 16; i <= 79; i++{
 96            tmpData[i] = f4(tmpData[i - 3^ tmpData[i - 8^ tmpData[i - 14^
 97                    tmpData[i - 16], 1);
 98        }

 99        int[] tmpabcde = new int[5];
100        for (int i1 = 0; i1 < tmpabcde.length; i1++{
101            tmpabcde[i1] = digestInt[i1];
102        }

103        for (int j = 0; j <= 19; j++{
104            int tmp = f4(tmpabcde[0], 5+
105                f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
106                tmpData[j] + 0x5a827999;
107            tmpabcde[4= tmpabcde[3];
108            tmpabcde[3= tmpabcde[2];
109            tmpabcde[2= f4(tmpabcde[1], 30);
110            tmpabcde[1= tmpabcde[0];
111            tmpabcde[0= tmp;
112        }

113        for (int k = 20; k <= 39; k++{
114            int tmp = f4(tmpabcde[0], 5+
115                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
116                tmpData[k] + 0x6ed9eba1;
117            tmpabcde[4= tmpabcde[3];
118            tmpabcde[3= tmpabcde[2];
119            tmpabcde[2= f4(tmpabcde[1], 30);
120            tmpabcde[1= tmpabcde[0];
121            tmpabcde[0= tmp;
122        }

123        for (int l = 40; l <= 59; l++{
124            int tmp = f4(tmpabcde[0], 5+
125                f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
126                tmpData[l] + 0x8f1bbcdc;
127            tmpabcde[4= tmpabcde[3];
128            tmpabcde[3= tmpabcde[2];
129            tmpabcde[2= f4(tmpabcde[1], 30);
130            tmpabcde[1= tmpabcde[0];
131            tmpabcde[0= tmp;
132        }

133        for (int m = 60; m <= 79; m++{
134            int tmp = f4(tmpabcde[0], 5+
135                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
136                tmpData[m] + 0xca62c1d6;
137            tmpabcde[4= tmpabcde[3];
138            tmpabcde[3= tmpabcde[2];
139            tmpabcde[2= f4(tmpabcde[1], 30);
140            tmpabcde[1= tmpabcde[0];
141            tmpabcde[0= tmp;
142        }

143        for (int i2 = 0; i2 < tmpabcde.length; i2++{
144            digestInt[i2] = digestInt[i2] + tmpabcde[i2];
145        }

146        for (int n = 0; n < tmpData.length; n++{
147            tmpData[n] = 0;
148        }

149    }

150    // 4字节数组转换为整数
151    private int byteArrayToInt(byte[] bytedata, int i) {
152        return ((bytedata[i] & 0xff<< 24| ((bytedata[i + 1& 0xff<< 16|
153        ((bytedata[i + 2& 0xff<< 8| (bytedata[i + 3& 0xff);
154    }

155    // 整数转换为4字节数组
156    private void intToByteArray(int intValue, byte[] byteData, int i) {
157        byteData[i] = (byte) (intValue >>> 24);
158        byteData[i + 1= (byte) (intValue >>> 16);
159        byteData[i + 2= (byte) (intValue >>> 8);
160        byteData[i + 3= (byte) intValue;
161    }

162    // 将字节转换为十六进制字符串
163    private static String byteToHexString(byte ib) {
164        char[] Digit = {
165                '0''1''2''3''4''5''6''7''8''9''A''B''C',
166                'D''E''F'
167            }
;
168        char[] ob = new char[2];
169        ob[0= Digit[(ib >>> 4& 0X0F];
170        ob[1= Digit[ib & 0X0F];
171        String s = new String(ob);
172        return s;
173    }

174    // 将字节数组转换为十六进制字符串
175    private static String byteArrayToHexString(byte[] bytearray) {
176        String strDigest = "";
177        for (int i = 0; i < bytearray.length; i++{
178            strDigest += byteToHexString(bytearray[i]);
179        }

180        return strDigest;
181    }

182    // 计算sha-1摘要,返回相应的字节数组
183    public byte[] getDigestOfBytes(byte[] byteData) {
184        process_input_bytes(byteData);
185        byte[] digest = new byte[20];
186        for (int i = 0; i < digestInt.length; i++{
187            intToByteArray(digestInt[i], digest, i * 4);
188        }

189        return digest;
190    }

191    // 计算sha-1摘要,返回相应的十六进制字符串
192    public String getDigestOfString(byte[] byteData) {
193        return byteArrayToHexString(getDigestOfBytes(byteData));
194    }

195    public static void main(String[] args) {
196        String data = "1";
197        System.out.println(data);
198        String digest = new SHA1().getDigestOfString(data.getBytes());
199        System.out.println(digest);
200    }

201}

202

在我们的一代令牌开发中,我们通过修改其部分源代码(重写sha1及相应的操作),实现otp在Android平台上的实现。其实我的工作量并不大,只是按要求把代码改了改,写一个SHA1类,加入了三个函数,包含初始化,数据更新,更新输出。以修改源代码中的过耦合现象,即digestInt数据不被随便修改,将其初始化过程实现在初始化函数中。

代码如下:
/**
* SHA1类,主要包含encrypt,init,upData,doFinal函数
@author Snowolf
*
*/public class SHA1{    
    
private final int[] abcde = {
            
0x674523010xefcdab890x98badcfe0x103254760xc3d2e1f0
        };
// 摘要数据存储数组
    private int[] digestInt = new int[5];
  
// 计算过程中的临时数据存储数组
       private int[] tmpData = new int[80];
    
/**
     * f1是SHA1算法中的一系列函数中的一个,操作32位字x,y,z并且产生32位字作为输出
     * 
@param x 32位字
     * 
@param y 32位字
     * 
@param z 32位字
     * 
@return 运算结果
     
*/
    
private int f1(int x, int y, int z) {
        
return (x & y) | (~& z);
    }
    
/**
     * f2是SHA1算法中的一系列函数中的一个,操作32位字x,y,z并且产生32位字作为输出
     * 
@param x 32位字
     * 
@param y 32位字
     * 
@param z 32位字
     * 
@return 运算结果
     
*/
    
private int f2(int x, int y, int z) {
        
return x ^ y ^ z;
    }
    
/**
     * f3是SHA1算法中的一系列函数中的一个,操作32位字x,y,z并且产生32位字作为输出
     * 
@param x 32位字
     * 
@param y 32位字
     * 
@param z 32位字
     * 
@return 运算结果
     
*/
    
private int f3(int x, int y, int z) {
        
return (x & y) | (x & z) | (y & z);
    }
    
/**
     * f4是循环移位函数,将x进行循环移位,移位次数为y
     * 
@param x 要移位的字
     * 
@param y 移位次数
     * 
@return 运算结果
     
*/
    
private int f4(int x, int y) {
        
return (x << y) | x >>> (32 - y);
    }
    
/**
     * 单元摘要计算函数,函数运算完成后,最终结果储存在digestInt中
     * 
@param Message_Block 为大小16个字的int型数组,即我们已经格式化完成的,要进行加密运算的数据
     * 
@return void
     * 
@author Snowolf
     
*/
    
private void encrypt(int[] Message_Block) {
        
for(int t = 0; t < 16; t++)
        {
            tmpData[t] 
= Message_Block[t];
        }
        
for (int i = 16; i <= 79; i++) {
            tmpData[i] 
= f4(tmpData[i - 3^ tmpData[i - 8^ tmpData[i - 14^
                    tmpData[i 
- 16], 1);
        }
        
int[] tmpabcde = new int[5];
        
for (int i1 = 0; i1 < tmpabcde.length; i1++) {
            tmpabcde[i1] 
= digestInt[i1]; 
        }
        
for (int j = 0; j <= 19; j++) {
            
int tmp = f4(tmpabcde[0], 5+
                f1(tmpabcde[
1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
                tmpData[j] 
+ 0x5a827999;
            tmpabcde[
4= tmpabcde[3];
            tmpabcde[
3= tmpabcde[2];
            tmpabcde[
2= f4(tmpabcde[1], 30);
            tmpabcde[
1= tmpabcde[0];
            tmpabcde[
0= tmp;
        }
        
for (int k = 20; k <= 39; k++) {
            
int tmp = f4(tmpabcde[0], 5+
                f2(tmpabcde[
1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
                tmpData[k] 
+ 0x6ed9eba1;
            tmpabcde[
4= tmpabcde[3];
            tmpabcde[
3= tmpabcde[2];
            tmpabcde[
2= f4(tmpabcde[1], 30);
            tmpabcde[
1= tmpabcde[0];
            tmpabcde[
0= tmp;
        }
        
for (int l = 40; l <= 59; l++) {
            
int tmp = f4(tmpabcde[0], 5+
                f3(tmpabcde[
1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
                tmpData[l] 
+ 0x8f1bbcdc;
            tmpabcde[
4= tmpabcde[3];
            tmpabcde[
3= tmpabcde[2];
            tmpabcde[
2= f4(tmpabcde[1], 30);
            tmpabcde[
1= tmpabcde[0];
            tmpabcde[
0= tmp;
        }
        
for (int m = 60; m <= 79; m++) {
            
int tmp = f4(tmpabcde[0], 5+
                f2(tmpabcde[
1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
                tmpData[m] 
+ 0xca62c1d6;
            tmpabcde[
4= tmpabcde[3];
            tmpabcde[
3= tmpabcde[2];
            tmpabcde[
2= f4(tmpabcde[1], 30);
            tmpabcde[
1= tmpabcde[0];
            tmpabcde[
0= tmp;
        }
        
for (int i2 = 0; i2 < tmpabcde.length; i2++) {
            digestInt[i2] 
= digestInt[i2] + tmpabcde[i2];//摘要存储在digestInt
        }
        
for (int n = 0; n < tmpData.length; n++) {
            tmpData[n] 
= 0;
        }
    }
    
/**
     * 初始化函数,将digestInt值初始化为SHA1算法中的原始初值
     
*/
    
public void init(){       
        System.arraycopy(abcde, 
0, digestInt, 0, abcde.length);
    }
    
/** SHA1加密运算,其中updata返回值为void,此时digestInt中的数据为计算结果(摘要)
     *为16个字的int型数组,即我们已经格式化完成的数据
     * 
@param Message_Block 为大小16个字的int型数组,即我们已经格式化完成的,要进行加密运算的数据
     * 
@author Snowolf
     
*/
    
public void upData(int[] Message_Block){
        encrypt(Message_Block);
    }
    
/**
     * SHA1加密运算,返回值为int[],即返回计算出来的摘要
     * 
@param Message_Block 为大小16个字的int型数组,即我们已经格式化完成的,要进行加密运算的数据
     * 
@return int[5]摘要
     * 
@author Snowolf
     
*/
    
public int[] doFinal(int[] Message_Block){
        
int[] doFinalInt = new int[5];
        encrypt(Message_Block);
        System.arraycopy(digestInt, 
0, doFinalInt, 0, digestInt.length);
        
return doFinalInt;
    }
}



代码如下:

  1/**
  2* SHA1类,主要包含encrypt,init,upData,doFinal函数
  3@author Snowolf
  4*
  5*/

  6public class SHA1{    
  7    private final int[] abcde = {
  8            0x674523010xefcdab890x98badcfe0x103254760xc3d2e1f0
  9        }
;
 10// 摘要数据存储数组
 11    private int[] digestInt = new int[5];
 12  // 计算过程中的临时数据存储数组
 13    
 14    private int[] tmpData = new int[80];
 15    /**
 16     * f1是SHA1算法中的一系列函数中的一个,操作32位字x,y,z并且产生32位字作为输出
 17     * @param x 32位字
 18     * @param y 32位字
 19     * @param z 32位字
 20     * @return 运算结果
 21     */

 22    private int f1(int x, int y, int z) {
 23        return (x & y) | (~& z);
 24    }

 25    /**
 26     * f2是SHA1算法中的一系列函数中的一个,操作32位字x,y,z并且产生32位字作为输出
 27     * @param x 32位字
 28     * @param y 32位字
 29     * @param z 32位字
 30     * @return 运算结果
 31     */

 32    private int f2(int x, int y, int z) {
 33        return x ^ y ^ z;
 34    }

 35    /**
 36     * f3是SHA1算法中的一系列函数中的一个,操作32位字x,y,z并且产生32位字作为输出
 37     * @param x 32位字
 38     * @param y 32位字
 39     * @param z 32位字
 40     * @return 运算结果
 41     */

 42    private int f3(int x, int y, int z) {
 43        return (x & y) | (x & z) | (y & z);
 44    }

 45    /**
 46     * f4是循环移位函数,将x进行循环移位,移位次数为y
 47     * @param x 要移位的字
 48     * @param y 移位次数
 49     * @return 运算结果
 50     */

 51    private int f4(int x, int y) {
 52        return (x << y) | x >>> (32 - y);
 53    }

 54    /**
 55     * 单元摘要计算函数,函数运算完成后,最终结果储存在digestInt中
 56     * @param Message_Block 为大小16个字的int型数组,即我们已经格式化完成的,要进行加密运算的数据
 57     * @return void
 58     * @author Snowolf
 59     */

 60    private void encrypt(int[] Message_Block) {
 61        for(int t = 0; t < 16; t++)
 62        {
 63            tmpData[t] = Message_Block[t];
 64        }

 65        for (int i = 16; i <= 79; i++{
 66            tmpData[i] = f4(tmpData[i - 3^ tmpData[i - 8^ tmpData[i - 14^
 67                    tmpData[i - 16], 1);
 68        }

 69        int[] tmpabcde = new int[5];
 70        for (int i1 = 0; i1 < tmpabcde.length; i1++{
 71            tmpabcde[i1] = digestInt[i1]; 
 72        }

 73        for (int j = 0; j <= 19; j++{
 74            int tmp = f4(tmpabcde[0], 5+
 75                f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
 76                tmpData[j] + 0x5a827999;
 77            tmpabcde[4= tmpabcde[3];
 78            tmpabcde[3= tmpabcde[2];
 79            tmpabcde[2= f4(tmpabcde[1], 30);
 80            tmpabcde[1= tmpabcde[0];
 81            tmpabcde[0= tmp;
 82        }

 83        for (int k = 20; k <= 39; k++{
 84            int tmp = f4(tmpabcde[0], 5+
 85                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
 86                tmpData[k] + 0x6ed9eba1;
 87            tmpabcde[4= tmpabcde[3];
 88            tmpabcde[3= tmpabcde[2];
 89            tmpabcde[2= f4(tmpabcde[1], 30);
 90            tmpabcde[1= tmpabcde[0];
 91            tmpabcde[0= tmp;
 92        }

 93        for (int l = 40; l <= 59; l++{
 94            int tmp = f4(tmpabcde[0], 5+
 95                f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
 96                tmpData[l] + 0x8f1bbcdc;
 97            tmpabcde[4= tmpabcde[3];
 98            tmpabcde[3= tmpabcde[2];
 99            tmpabcde[2= f4(tmpabcde[1], 30);
100            tmpabcde[1= tmpabcde[0];
101            tmpabcde[0= tmp;
102        }

103        for (int m = 60; m <= 79; m++{
104            int tmp = f4(tmpabcde[0], 5+
105                f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4+
106                tmpData[m] + 0xca62c1d6;
107            tmpabcde[4= tmpabcde[3];
108            tmpabcde[3= tmpabcde[2];
109            tmpabcde[2= f4(tmpabcde[1], 30);
110            tmpabcde[1= tmpabcde[0];
111            tmpabcde[0= tmp;
112        }

113        for (int i2 = 0; i2 < tmpabcde.length; i2++{
114            digestInt[i2] = digestInt[i2] + tmpabcde[i2];//摘要存储在digestInt
115        }

116        for (int n = 0; n < tmpData.length; n++{
117            tmpData[n] = 0;
118        }

119    }

120    /**
121     * 初始化函数,将digestInt值初始化为SHA1算法中的原始初值
122     */

123    public void init(){       
124        System.arraycopy(abcde, 0, digestInt, 0, abcde.length);
125    }

126    /** SHA1加密运算,其中updata返回值为void,此时digestInt中的数据为计算结果(摘要)
127     *为16个字的int型数组,即我们已经格式化完成的数据
128     * @param Message_Block 为大小16个字的int型数组,即我们已经格式化完成的,要进行加密运算的数据
129     * @author Snowolf
130     */

131    public void upData(int[] Message_Block){
132        encrypt(Message_Block);
133    }

134    /**
135     * SHA1加密运算,返回值为int[],即返回计算出来的摘要
136     * @param Message_Block 为大小16个字的int型数组,即我们已经格式化完成的,要进行加密运算的数据
137     * @return int[5]摘要
138     * @author Snowolf
139     */

140    public int[] doFinal(int[] Message_Block){
141        int[] doFinalInt = new int[5];
142        encrypt(Message_Block);
143        System.arraycopy(digestInt, 0, doFinalInt, 0, digestInt.length);
144        return doFinalInt;
145    }

146}

147
posted on 2010-11-22 14:48 WangShishuai 阅读(1114) 评论(1)  编辑  收藏 所属分类: AndroidJava加密算法

Feedback

# re: SHA-1的Java实现 及在otp中的使用 2013-04-30 01:40 M.LI
你好:我在读你的http://www.blogjava.net/BigForest/archive/2010/11/22/338691.html
这个文章,我是菜鸟想借鉴一下在OTP中的使用,但是我没找到在里面 的用法,求指导……
我 的邮箱hpucode@gmail.com  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: