最初是下载了一个写好了的Java版SHA1,代码如下:
来源:
http://blog.csdn.net/zyg158/archive/2007/06/26/1667531.aspx
1public class SHA1 {
2 private final int[] abcde = {
3 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
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++] = (byte) 0x80;
57 // 补0操作
58 for (int i = 0; i < zeros; i++) {
59 newbyte[l++] = (byte) 0x00;
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) | (~x & 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 = {
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
};
// 摘要数据存储数组
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) | (~x & 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 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
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) | (~x & 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