MD5加密解密_计算机软件及应用_IT计算机_专业资料.ppt
- 格式:ppt
- 大小:1.31 MB
- 文档页数:16


md5加密解密一个例子import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.io.*;import java.security.*;import javax.crypto.*;import javax.crypto.spec.*;/**文件名:FileEncrypter.javaJDK:1.40以上说明:文件加密加密方法:三重DES加密加密过程:对选中的文件加密后在同文件夹下生成一个增加了".tdes"扩展名的加密文件解密过程:对选中的加密文件(必须有".tdes"扩展名)进行解密*/public class FileEncrypter extends JFrame{public static final int WIDTH = 550;public static final int HEIGHT = 200;public static void main(String args[]) {FileEncrypter fe = new FileEncrypter();fe.show();}FileEncrypter(){this.setSize(WIDTH,HEIGHT);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setResizable(false);Toolkit tk = Toolkit.getDefaultT oolkit(); Dimension screenSize = tk.getScreenSize();this.setLocation((screenSize.width - WIDTH)/2, (screenSize.height - HEIGHT)/2);this.setTitle("文件加密器(TriDES)");Container c = this.getContentPane();c.setLayout( new FlowLayout());final FilePanel fp = new FilePanel("文件选择");c.add(fp);final KeyPanel pp = new KeyPanel("密码");c.add(pp);JButton jbE = new JButton("加密");c.add(jbE);jbE.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent event){ File file = new File(fp.getFileName());if (file.exists())encrypt(file.getAbsoluteFile(),pp.getKey());elseJOptionPane.showMessageDialog(null,"请选择文件!","提示",JOptionPane.OK_OPTION); }});JButton jbD = new JButton("解密");c.add(jbD);jbD.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent event){ File file = new File(fp.getFileName());if (file.exists())decrypt(file.getAbsoluteFile(),pp.getKey());elseJOptionPane.showMessageDialog(null,"请选择文件!","提示",JOptionPane.OK_OPTION);}});}/**加密函数输入:要加密的文件,密码(由0-F组成,共48个字符,表示3个8位的密码)如:AD67EA2F3BE6E5ADD368DFE03120B5DF92A8FD8FEC2F074 6其中:AD67EA2F3BE6E5AD DES密码一D368DFE03120B5DF DES密码二92A8FD8FEC2F0746 DES密码三输出:对输入的文件加密后,保存到同一文件夹下增加了".tdes"扩展名的文件中。
MD5破解技巧1.概述MD5(Message Digest Algorithm 5)是一种常见的哈希算法,用于将任意长度的数据转化为128位的固定长度摘要。
由于MD5是单向不可逆的算法,因此在实际应用中经常被用于密码存储和数字签名等场景。
然而,随着计算能力的增强,传统的MD5算法已经变得越来越容易受到暴力破解的攻击。
在本文中,我们将探讨一些MD5破解的常用技巧,帮助您更好地了解如何应对MD5的安全风险。
2.字典攻击字典攻击是一种常见的MD5破解技巧,它基于事先准备好的密码字典来尝试破解MD5摘要。
字典通常包含常见密码、常用字典、尊称、生日等可能的密码组合。
在实际应用中,我们可以使用一些常见的密码字典,如”rockyou.txt”、“password.txt”等。
通过将这些密码字典与目标MD5摘要进行比对,我们可以有效地找出可能的明文密码。
然而,对于较复杂、随机组合的密码,字典攻击会变得不太有效。
在进行MD5破解时,我们还需要考虑其他的技巧。
3.暴力破解暴力破解是一种耗时较长的MD5破解方法,它通过尝试所有可能的密码组合来逐个验证MD5摘要。
这种方法需要消耗大量的计算资源和时间,但对于任何密码都具有一定的破解成功率。
在实践中,我们可以使用一些专门的密码破解工具,如Hashcat、John the Ripper等,来执行暴力破解。
这些工具通常支持并行计算和分布式破解,能够加快破解速度。
然而,暴力破解方法的破解速度与密码长度和复杂性成正比。
当面对较长、复杂的密码时,暴力破解可能需要非常长的时间。
4.彩虹表攻击彩虹表攻击是一种基于预先计算的技术,用于破解MD5摘要。
它通过事先计算出明文密码和对应的MD5摘要的映射关系,并将其保存在一个巨大的彩虹表中。
在进行破解时,只需要在彩虹表中查找对应的MD5摘要即可获得明文密码。
彩虹表攻击具有较高的破解速度,但需要花费大量的存储空间和计算资源来构建和查询彩虹表。
在实际应用中,我们可以使用一些现成的彩虹表,如”oclHashcat-plus”等。
MD5加密算法详解MD5(Message Digest Algorithm 5)是一种常见的哈希算法,用于将任意长度的信息转换为固定长度(通常为128位)的输出。
它是MD4算法的改进版本,由Ron Rivest在1991年设计。
MD5算法在密码学和数据完整性检查方面被广泛应用。
1.算法概述:MD5算法的输入是任意长度的消息,输出是一个128位(32个字符)的消息摘要。
这个摘要是唯一的,即使消息只有微小的变化,它的摘要也会有较大的差异。
MD5具有以下特点:-可逆性:MD5是单向散列函数,即不能从摘要中恢复原始消息。
这意味着无法通过知道MD5摘要的人来确定原始消息,所以MD5算法通常用于验证消息的完整性。
-高度可靠性:MD5算法能够快速计算,且其输出分布均匀,几乎每个消息都有不同的摘要。
-高速性:MD5算法的计算速度非常快,在软件和硬件上都可以轻松实现。
2.算法步骤:MD5算法的核心包括四个基本步骤:填充、初始化、循环操作和输出。
下面是详细的步骤说明:-填充:首先将消息进行填充,使其长度(以比特位为单位)满足对512求余等于448、填充的格式为一个1后面跟随若干个0,然后是64位的原始消息长度。
-初始化:使用4个固定的32位字作为初始变量(A、B、C、D),这些变量用于存储中间摘要和最终摘要。
-循环操作:MD5算法使用了64个循环运算来处理填充后的消息。
在每个循环中,输入消息的一部分被处理,并按照一系列算法步骤进行变换,然后将变换的结果添加到当前状态变量中。
-输出:循环运算结束后,将中间变量连接起来形成最终的128位摘要。
最终的结果可以表示为一个32位的十六进制数。
3.安全性:尽管MD5算法在之前被广泛应用于检验文件完整性和密码验证等领域,但现在已经不再被认为是安全的。
主要原因有:-容易受到碰撞攻击:由于MD5算法的输出空间相对较小(只有128位),因此存在相同摘要的不同输入。
这使得攻击者可以通过找到相同摘要的两个不同输入来冒充验证身份或篡改数据。
MD5加密算法/* MD5lib.h - md5 library*//* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All rights reserved.RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this softwarefor any particular purpose. It is provided "as is" without express or implied warranty of any kind.These notices must be retained in any copies of any part of this documentation and/or software.*//* The following makes MD default to MD5 if it has not already been defined with C compiler flags.*/#include <stdio.h>#include <time.h>#include <string.h>#define MD 5/* GLOBAL.H - RSAREF types and constants*//* PROTOTYPES should be set to one if and only if the compiler supportsfunction argument prototyping.The following makes PROTOTYPES default to 0 if it has not already been defined with C compiler flags.*/#ifndef PROTOTYPES#define PROTOTYPES 0#endif/* POINTER defines a generic pointer type */typedef unsigned char *POINTER;/* UINT2 defines a two byte word */typedef unsigned short int UINT2;/* UINT4 defines a four byte word */ typedef unsigned long int UINT4;/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list.*/#if PROTOTYPES#define PROTO_LIST(list) list #else#define PROTO_LIST(list) ()#endif/* Length of test block, number of test blocks.*/#define TEST_BLOCK_LEN 1000#define TEST_BLOCK_COUNT 1000/* Constants for MD5Transform routine.*/#define S11 7#define S12 12#define S13 17#define S14 22#define S21 5#define S22 9#define S23 14#define S24 20#define S31 4#define S32 11#define S33 16#define S34 23#define S41 6#define S42 10#define S43 15#define S44 21char* MDString PROTO_LIST ((char *)); char* MDFile PROTO_LIST ((char *)); char* hmac_md5(char* text, char* key);typedef struct {UINT4 state[4]; /* state (ABCD) */UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */unsigned char buffer[64]; /* input buffer */ } MD5_CTX;/*void MD5Init PROTO_LIST ((MD5_CTX *));void MD5Update PROTO_LIST((MD5_CTX *, unsigned char *, unsigned int));void MD5Final PROTO_LIST ((unsigned char [16], MD5_CT X *));static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); static void Encode PROTO_LIST((unsigned char *, UINT4 *, unsigned int));static void Decode PROTO_LIST((UINT4 *, unsigned char *, unsigned int));static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); */ static unsigned char PADDING[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* F, G, H and I are basic MD5 functions.*/#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))#define H(x, y, z) ((x) ^ (y) ^ (z))#define I(x, y, z) ((y) ^ ((x) | (~z)))/* ROTATE_LEFT rotates x left n bits.*/#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.Rotation is separate from addition to prevent recomputation.*/#define FF(a, b, c, d, x, s, ac) {(a)+=F((b), (c), (d)) + (x) +(UINT4)(ac);(a)= ROTATE_LEFT((a),(s)); (a)+=(b);}#define GG(a, b, c, d, x, s, ac) {(a) += G ((b), (c), (d)) + (x) +(UINT4)(ac);(a) = ROTATE_LEFT ((a), (s)); (a) += (b);}#define HH(a, b, c, d, x, s, ac) {(a) += H ((b), (c), (d)) + (x) +(UINT4)(ac);(a)= ROTATE_LEFT ((a), (s)); (a) += (b);}#define II(a, b, c, d, x, s, ac) {(a) += I ((b), (c), (d)) + (x) +(UINT4)(ac);(a)= ROTATE_LEFT ((a), (s)); (a) += (b);}void MD5Init (MD5_CTX *context);void MD5Update(MD5_CTX *context, unsigned char *input,unsigned int inputLen);void MD5Final (unsigned char digest[16], MD5_CTX *context); staticvoid MD5Transform (UINT4 [4], unsigned char [64]) ; static voidEncode(unsigned char *, UINT4 *, unsigned int); static void Decode(UINT4 *, unsigned char *, unsigned int); static void MD5_memcpy(POINTER, POINTER, unsigned int); static void MD5_memset(POINTER, int, unsigned int);/* MD5 initialization. Begins an MD5 operation, writing a newcontext.*/void MD5Init (MD5_CTX *context)/* context */ {context->count[0] = context->count[1] = 0;/* Load magic initialization constants.*/context->state[0] = 0x67452301;context->state[1] = 0xefcdab89;context->state[2] = 0x98badcfe;context->state[3] = 0x10325476;}/* MD5 block update operation. Continues an MD5 message-digestoperation, processing another message block, and updating thecontext.*/void MD5Update (MD5_CTX *context, unsigned char *input,unsigned int inputLen )/* context *//* input block *//* length of input block */ {unsigned int i, index, partLen;/* Compute number of bytes mod 64 */index = (unsigned int)((context->count[0] >> 3) & 0x3F);/* Update number of bits */if ((context->count[0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))context->count[1]++;context->count[1] += ((UINT4)inputLen >> 29);partLen = 64 - index;/* Transform as many times as possible.*/if (inputLen >= partLen) {MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform (context->state, context->buffer);for (i = partLen; i + 63 < inputLen; i += 64)MD5Transform (context->state, &input[i]);index = 0;}elsei = 0;/* Buffer remaining i MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);}/* MD5 finalization. Ends an MD5 message-digest operation, writing thethe message digest and zeroizing the context.*/void MD5Final (unsigned char digest[16], MD5_CTX *context)/* message digest *//* context */ {unsigned char bits[8];unsigned int index, padLen;/* Save number of bits */Encode (bits, context->count, 8);/* Pad out to 56 mod 64.*/index = (unsigned int)((context->count[0] >> 3) & 0x3f);padLen = (index < 56) ? (56 - index) : (120 - index);MD5Update (context,(unsigned char*) PADDING, padLen);/* Append length (before padding) */MD5Update (context, bits, 8);/* Store state in digest */Encode (digest, context->state, 16);/* Zeroize sensitive information.*/MD5_memset ((POINTER)context, 0, sizeof (*context)); }/* MD5 basic transformation. Transforms state based on block.*/static void MD5Transform (UINT4 state[4], unsigned char block[64]) {int i=0;UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64);/* Round 1 */FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 *//* Round 2 */GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 *//* Round 3 */HH (a, b, c, d, x[ 5], S31, HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */state[0] += a;state[1] += b;state[2] += c;state[3] += d;/* Zeroize sensitive information.*/MD5_memset ((POINTER)x, 0, sizeof (x)); }/* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4.*/static void Encode (unsigned char *output, UINT4 *input,unsigned int len){unsigned int i, j;for (i = 0, j = 0; j < len; i++, j += 4) {output[j] = (unsigned char)(input[i] & 0xff);output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);}}/* Decodes input (unsigned char) into output (UINT4). Assumes len isa multiple of 4.*/static void Decode (UINT4 *output,unsigned char *input,unsigned int len){unsigned int i, j;for (i = 0, j = 0; j < len; i++, j += 4)output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);}/* Note: Replace "for loop" with standard memcpy if possible. */static void MD5_memcpy (POINTER output, POINTER input, unsigned int len){unsigned int i;for (i = 0; i < len; i++)output[i] = input[i];}/* Note: Replace "for loop" with standard memset if possi */ static void MD5_memset (POINTER output, int value, unsigned int len){unsigned int i;for (i = 0; i < len; i++)((char *)output)[i] = (char)value; }/* Digests a string and prints the result.*/char* MDString (char *string){MD5_CTX context;unsigned char digest[16];char output1[32];static char output[33]={""};unsigned int len = strlen (string);int i;MD5Init (&context);MD5Update (&context, (unsigned char*)string, len);MD5Final (digest, &context);for (i = 0; i < 16; i++){sprintf(&(output1[2*i]),"%02x",(unsigned char)digest[i]); sprintf(&(output1[2*i+1]),"%02x",(unsigned char)(digest[i]<<4)); }for(i=0;i<32;i++)output[i]=output1[i];return output;}/* Digests a file and prints the result.*/char* MDFile (char *filename){ static char output[33]={""};FILE *file;MD5_CTX context;int len;unsigned char buffer[1024], digest[16];int i;char output1[32];if ((file = fopen (filename, "rb")) == NULL){ printf ("%s can't be openedn", filename);return 0;}else {MD5Init (&context);while (len = fread (buffer, 1, 1024, file))MD5Update (&context, buffer, len);MD5Final (digest, &context);fclose (file);for (i = 0; i < 16; i++){sprintf(&(output1[2*i]),"%02x",(unsigned char)digest[i]); sprintf(&(output1[2*i+1]),"%02x",(unsigned char)(digest[i]<<4)); }for(i=0;i<32;i++)output[i]=output1[i];return output;}}char* hmac_md5(char* text,char* key) {char digest[16];char output1[32];static char output[33]={""};MD5_CTX context;unsigned char k_ipad[65]; /* inner padding -* key XORd with ipad*/unsigned char k_opad[65]; /* outer padding -* key XORd with opad*/unsigned char tk[16];int i;int text_len = strlen (text);int key_len=strlen(key);/* if key is longer than 64 bytes reset it to key=MD5(key) */ if (key_len > 64) {MD5_CTX tctx;MD5Init(&tctx);MD5Update(&tctx,(unsigned char*) key, key_len); MD5Final(tk, &tctx);key = (char*)tk;key_len = 16;}/** the HMAC_MD5 transform looks like:** MD5(K XOR opad, MD5(K XOR ipad, text))** where K is an n byte key* ipad is the byte 0x36 repeated 64 times* opad is the byte 0x5c repeated 64 times* and text is the data being protected*//* start out by storing key in pads *//*bzero( k_ipad, sizeof k_ipad);bzero( k_opad, */for(i=0;i<65;i++)k_ipad[i]=(unsigned char)0;for(i=0;i<65;i++)k_opad[i]=(unsigned char)0;/*bcopy( key, k_ipad, key_len);bcopy( key, k_opad, key_len);*/for(i=0;i<key_len;i++){k_ipad[i]=(unsigned char)key[i];k_opad[i]=(unsigned char)key[i];}/* XOR key with ipad and opad values */for (i=0; i<64; i++) {k_ipad[i] ^= 0x36;k_opad[i] ^= 0x5c;}/** perform inner MD5*/MD5Init(&context); /* init context for 1st* pass */MD5Update(&context, k_ipad, 64); /* start with inner pad */MD5Update(&context, (unsigned char*)text, text_len); /* then text of datagram*/MD5Final((unsigned char*)digest, &context); /* finish up 1st pass */ /** perform outer MD5*/MD5Init(&context); /* init context for 2nd* pass */MD5Update(&context, k_opad, 64); /* start with outer pad */MD5Update(&context,(unsigned char*) digest, 16); /* then results of 1st* hash */MD5Final((unsigned char*)digest, &context); /* finish up 2nd pass */ for (i = 0; i < 16; i++){sprintf(&(output1[2*i]),"%02x",(unsigned char)digest[i]);sprintf(&(output1[2*i+1]),"%02x",(unsigned char)(digest[i]<<4));}for(i=0;i<32;i++)output[i]=output1[i];return output;}。