C/C++ Java HmacSha1加密算法 Base64處理 URLencode


因工作需要、平台轉接。第三方給出的是Java下的Hmac_sha1加密接口方式。

Java部分 

Java源碼
Java版源碼

Java版
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
importpublic class Signature {

    private static final String HMAC_SHA1 = "HmacSHA1";
 /*加密實現,采取加密方式為HMACSHA1 ,返回的是base64處理后的*/
    public static String generateSignature(String data, String appSecret) {
        byte[] byteHMAC = null;
        try {
            Mac mac = Mac.getInstance(HMAC_SHA1);
            SecretKeySpec spec = new SecretKeySpec(appSecret.getBytes(),HMAC_SHA1);
            mac.init(spec);
            byteHMAC = mac.doFinal(data.getBytes());
             String str1=BytesToStr(byteHMAC);

             System.out.println("輸出字符數組,未經Base64處理");
             System.out.println(str1);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException ignore) {
            // should never happen
        }

        return new String(Base64.encode(byteHMAC));
    }

    
      /*加密實現,采取加密方式為HMACSHA1 ,返回的是轉化為16進制的*/
    public static String getSignature(String data,String key) throws Exception{  
          byte[] keyBytes=key.getBytes();  
           SecretKeySpec signingKey = new SecretKeySpec(keyBytes, HMAC_SHA1);     
        Mac mac = Mac.getInstance(HMAC_SHA1);     
        mac.init(signingKey);     
         byte[] rawHmac = mac.doFinal(data.getBytes()); 
         String str1=BytesToStr(rawHmac);
         System.out.println("輸出字符數組");
         System.out.println(str1);
        StringBuilder sb=new StringBuilder();  
         for(byte b:rawHmac){  
              sb.append(byteToHexString(b));  
             }  
         return sb.toString();    
         
        }  
           
    public static String byteToHexString(byte ib){  
         char[] Digit={  
       '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'  
          };  
        char[] ob=new char[2];  
         ob[0]=Digit[(ib>>>4)& 0X0f];  
         ob[1]=Digit[ib & 0X0F];  
         String s=new String(ob);  
          return s;           
         }       
      
    public static String BytesToStr(byte[] target)
    {
     StringBuffer buf = new StringBuffer();
     for (int i = 0, j = target.length; i < j; i++) {
      buf.append((char) target[i]);
     }
     return buf.toString();
    }



    /**
     * @param value
     *            string to be encoded
     */
    public static String encode(String value) {
        String encoded = null;
        try {
            encoded = URLEncoder.encode(value, "UTF-8");
        } catch (UnsupportedEncodingException ignore) {
        }
        StringBuffer buf = new StringBuffer(encoded.length());
        char focus;
        for (int i = 0; i < encoded.length(); i++) {
            focus = encoded.charAt(i);
            if (focus == '*') {
                buf.append("%2A");
            } else if (focus == '+') {
                buf.append("%20");
            } else if (focus == '%' && (i + 1) < encoded.length()
                    && encoded.charAt(i + 1) == '7'
                    && encoded.charAt(i + 2) == 'E') {
                buf.append('~');
                i += 2;
            } else {
                buf.append(focus);
            }
        }
        return buf.toString();
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
          
                 try {
            //第一種方式
            System.out.println("---------------參數encode----------------------");
            String name=generateSignature(("老朋友", "123");
            System.out.println("----------加密----------------------");
            System.out.println(name);
            System.out.println("----------壓縮------------------------------");
            System.out.println(URLEncoder.encode(name, "UTF-8"));
            System.out.println("---------------------------------------------");
            
            
        } catch (UnsupportedEncodingException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }

        try {
           //第二種方式  可以經過Base64算法原理實現 
            String name=getSignature("老朋友","123");
            System.out.println(name);
            System.out.println(URLEncoder.encode(name,"UTF-8"));
          //
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

1、創建Mac對象,初始化加密算法的類型。   測試數據為 ("漸入圍城","123")    (“jianruweicheng”,“123”)

      Mac mac = Mac.getInstance(HMAC_SHA1);   其中 HMAC_SHA1,覺得應該是枚舉中的一個。

  Mac類 其導入的包為jce.jar包, 文件為:jce.src\javax\crypto\Mac.java。

      再次追蹤為

                sun.security.jca.GetInstance;

                   java.security.Signature;

This Signature class is used to provide applications the functionality of a digital signature algorithm. Digital signatures are used for authentication and integrity assurance of digital data.(Signature類是用來為應用程序提供的功能數字簽名算法數字簽名用於數字數據的認證和完整性保證

The signature algorithm can be, among others, the NIST standard DSA, using DSA and SHA-1. The DSA algorithm using the SHA-1 message digest algorithm can be specified as SHA1withDSA. In the case of RSA, there are multiple choices for the message digest algorithm, so the signing algorithm could be specified as, for example, MD2withRSA, MD5withRSA, or SHA1withRSA. The algorithm name must be specified, as there is no default.(谷歌翻譯:。。簽名算法其中包括NIST標准DSA使用DSASHA-1可以指定使用SHA-1消息摘要算法的DSA算法SHA1的DSARSA的情況下有多個選擇報文摘要算法,所以可以被指定為,例如,MD2withRSA,MD5withRSA,或SHA1withRSA簽名算法必須指定算法名稱,因為沒有默認的

A Signature object can be used to generate and verify digital signatures.(Signature對象可用來生成和驗證數字簽名

2、對秘鑰進行加工

SecretKeySpec spec = new SecretKeySpec(appSecret.getBytes(), HMAC_SHA1); 參數String appSecret

追蹤為 :javax.crypto.spec.SecretKeySpec   將原文秘鑰轉為字節數組,只可用於那些沒有其他參數的加密秘鑰。

3、用生成的秘鑰字節數組初始化mac對象。

  mac.init(spec);

4、將待加密的文本數組,用mac對象進行處理。

 byteHMAC = mac.doFinal(data.getBytes());  

     /* 經過下列代碼輸出

       String str1=BytesToStr(byteHMAC);     

      System.out.println(str1);    輸出后結果  ᄇiWᅦ[マᄁyワWl■7.Nヨ

    */

5、返回字符串。

5.1  返回經過Base64處理, 對應的 String generateSignature(String data, String appSecret) 方法:

return new String(Base64.encode(byteHMAC)); 

     /*

              打印輸出為 smlXx1uPoh55nFdsf+0WNy4BTpY=

    */

5.2 返回轉化為16進制的字符串 對應的 String getSignature(String data,String key) 方法

    StringBuilder sb=new StringBuilder(); 
             for(byte b:rawHmac){ 
              sb.append(byteToHexString(b)); 
              } 
             return sb.toString();

      /* 

    打印輸出為:b26957c75b8fa21e799c576c7fed16372e014e96

    */

 

         由方式2轉化為方式1的方式為 Base64編碼。 每三個字節(byte)轉換為四個字符。以前三位為例 “b26..”

       b26-> 1011  0010 0110 ,根據規則 右移2位 00101100|00100110,構成。

       計算 第一個為 44(查表為s),第二個為38(查表為m).

       對應方式1中經過Base64轉化的 “sm....”

6、主函數  簡化版

public static void main(String[] args) {   

     String name=generateSignature("漸入圍城","123");    

 System.out.println(name);   // smlXx1uPoh55nFdsf+0WNy4BTpY=

 System.out.println(URLEncoder.encode(name, "UTF-8"));    //經過Encode處理話,會將'='等字符轉化為  ‘%3D’類似

 System.out.println("---------------------------------------------");   

 String name=getSignature("漸入圍城","123");   

 System.out.println(name);   //打印輸出為:b26957c75b8fa21e799c576c7fed16372e014e96

 System.out.println(getSignature("jianruweicheng", "123"));  //打印輸出為:71abcdf5b3c4285678787e2b72fed9db11296c27

  }

 

C語言版

HMACSHA1.C文件

C版
#include "sha1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#ifndef SHA_DIGESTSIZE
#define SHA_DIGESTSIZE 20
#endif

#ifndef SHA_BLOCKSIZE
#define SHA_BLOCKSIZE 64
#endif


/* Hash a single 512-bit block. This is the core of the algorithm. */

void SHA1Transform(__u32 state[5], __u8 buffer[64])
{
__u32 a, b, c, d, e;
typedef union {
    unsigned char c[64];
    __u32 l[16];
} CHAR64LONG16;

CHAR64LONG16* block;

#ifdef SHA1HANDSOFF

static unsigned char workspace[64];
    block = (CHAR64LONG16*)workspace;
//    NdisMoveMemory(block, buffer, 64);
    memcpy(block, buffer, 64);
#else
    block = (CHAR64LONG16*)buffer;
#endif
    /* Copy context->state[] to working vars */
    a = state[0];
    b = state[1];
    c = state[2];
    d = state[3];
    e = state[4];
    /* 4 rounds of 20 operations each. Loop unrolled. */
    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
    /* Add the working vars back into context.state[] */
    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
    state[4] += e;
    /* Wipe variables */
    a = b = c = d = e = 0;
}


/* SHA1Init - Initialize new context */

void SHA1Init(SHA1_CTX* context)
{
    /* SHA1 initialization constants */
    context->state[0] = 0x67452301;
    context->state[1] = 0xEFCDAB89;
    context->state[2] = 0x98BADCFE;
    context->state[3] = 0x10325476;
    context->state[4] = 0xC3D2E1F0;
    context->count[0] = context->count[1] = 0;
}


/* Run your data through this. */

void SHA1Update(SHA1_CTX* context, unsigned char* data, __u32 len)
{
    __u32 i, j;

    j = context->count[0];
    if ((context->count[0] += len << 3) < j)
    context->count[1]++;
    context->count[1] += (len>>29);
    j = (j >> 3) & 63;
    if ((j + len) > 63) {
//        NdisMoveMemory(&context->buffer[j], data, (i = 64-j));
        memcpy(&context->buffer[j], data, (i = 64-j));
        SHA1Transform(context->state, context->buffer);
        for ( ; i + 63 < len; i += 64) {
            SHA1Transform(context->state, &data[i]);
        }
        j = 0;
    }
    else i = 0;
//    NdisMoveMemory(&context->buffer[j], &data[i], len - i);
    memcpy(&context->buffer[j], &data[i], len - i);
}


/* Add padding and return the message digest. */

void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
{
__u32 i, j;
unsigned char finalcount[8];

    for (i = 0; i < 8; i++) {
        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
    }
    SHA1Update(context, (unsigned char *)"\200", 1);
    while ((context->count[0] & 504) != 448) {
        SHA1Update(context, (unsigned char *)"\0", 1);
    }
    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
    for (i = 0; i < 20; i++) {
        digest[i] = (unsigned char)
         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
    }
    /* Wipe variables */
    i = j = 0;
//    NdisZeroMemory(context->buffer, 64);
//    NdisZeroMemory(context->state, 20);
//    NdisZeroMemory(context->count, 8);
//    NdisZeroMemory(&finalcount, 8);
    memset(context->buffer, 0x00, 64);
    memset(context->state, 0x00, 20);
    memset(context->count, 0x00, 8);
    memset(&finalcount, 0x00, 8);
    
#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite its own static vars */
    SHA1Transform(context->state, context->buffer);
#endif
}



/* Function to print the digest 
   打印輸出*/
void pr_sha(FILE* fp, unsigned char* s, int t)
{
    int i ;

    for(i=0;i<t;i++)
    printf("%02x",s[i]);    
    printf("\n");

}

void truncate
(
    char* d1, /* data to be truncated */
    char* d2, /* truncated data */
    int len /* length in bytes to keep */
)
{
    int i ;
    for (i = 0 ; i < len ; i++) d2[i] = d1[i];
}

/* Function to compute the digest
   加密算法的主要操作函數 */
void hmac_sha
(
    char* k,    /* 秘鑰 secret key */
    int lk,     /*  秘鑰長度 length of the key in bytes */
    char* d,    /* 數據 data */
    int ld,     /*  數據長度 length of data in bytes */
    char* out,  /* 輸出的字符串 output buffer, at least "t" bytes */
    int t
)
{
    SHA1_CTX ictx, octx ;
    char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE] ;
    char key[SHA_DIGESTSIZE] ;
    char buf[SHA_BLOCKSIZE] ;
    int i ;

    if (lk > SHA_BLOCKSIZE)
    {
        SHA1_CTX tctx ;
    SHA1Init(&tctx) ;
    SHA1Update(&tctx, k, lk) ;
    SHA1Final(key, &tctx) ;

    k = key ;
    lk = SHA_DIGESTSIZE ;
    }

/**** Inner Digest ****/

    SHA1Init(&ictx) ;

    /* Pad the key for inner digest */
    for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ;
    for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ;

    SHA1Update(&ictx, buf, SHA_BLOCKSIZE) ;
    SHA1Update(&ictx, d, ld) ;

    SHA1Final(isha, &ictx) ;

/**** Outter Digest ****/

    SHA1Init(&octx) ;

/* Pad the key for outter digest */

    for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ;
    for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ;

    SHA1Update(&octx, buf, SHA_BLOCKSIZE) ;
    SHA1Update(&octx, isha, SHA_DIGESTSIZE) ;

    SHA1Final(osha, &octx) ;

/* truncate and print the results */
    t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t ;
    truncate(osha, out, t) ;
    pr_sha(stdout, out, t) ;

}


int main()
{
    char k[1024],d[1024],out[1024] ;    
    int lk,ld,t;
    strcpy(d,"jianruweicheng");
    strcpy(k,"123");

    lk=strlen(k);
    ld=strlen(d);
    printf("lk=%d\n",lk);
    printf("ld=%d\n",ld);
    t=20;
    hmac_sha(k,lk,d,ld,out,t);

    return 0;
}

sha1.h文件

sha1.h源碼
#ifndef _IPSEC_SHA1_H_

#define _IPSEC_SHA1_H_


typedef unsigned long    __u32;
typedef unsigned char    __u8;

typedef struct
{
    __u32 state[5];
    __u32 count[2];
    __u8  buffer[64];
} SHA1_CTX;

#if defined(rol)
#undef rol
#endif

#define SHA1HANDSOFF

#define __LITTLE_ENDIAN 

#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))

/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifdef __LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
    |(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
    ^block->l[(i+2)&15]^block->l[i&15],1))

/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);


/* Hash a single 512-bit block. This is the core of the algorithm. */

void SHA1Transform(__u32 state[5], __u8 buffer[64]);
void SHA1Init(SHA1_CTX *context);
void SHA1Update(SHA1_CTX *context, unsigned char *data, __u32 len);
void SHA1Final(unsigned char digest[20], SHA1_CTX *context);
//void hmac_sha1(unsigned char *to_mac,unsigned int to_mac_length, unsigned char *key,unsigned int key_length, unsigned char *out_mac);
 

#endif /* _IPSEC_SHA1_H_ */


測試數據  文本 jianruweicheng 秘鑰 123  結果 為  71abcdf5b3c4285678787e2b72fed9db11296c27

C語言 hmacsha1加密結果

說明:如果用“漸入圍城”  得出的結果 為 3f862d26e2410c4ab43e2d162f39d2e8ff82927a ,與上文Java版 5.2的結果不一樣

原因:漢字編碼在不同的編譯環境中,有不同的編碼格式。必須轉化為對應的格式(本文統一為 UTF-8)才能與上文Java版的 5.2想匹配。

 

C++ 版

SHA1類
 主要的加密算法核心

SHA1類
SHA1。h

#ifndef ___SHA1_HDR___
#define ___SHA1_HDR___

#if !defined(SHA1_UTILITY_FUNCTIONS) && !defined(SHA1_NO_UTILITY_FUNCTIONS)
#define SHA1_UTILITY_FUNCTIONS
#endif

#include <memory.h> // Needed for memset and memcpy

#ifdef SHA1_UTILITY_FUNCTIONS
#include <stdio.h>  // Needed for file access and sprintf
#include <string.h> // Needed for strcat and strcpy
#endif

#ifdef _MSC_VER
#include <stdlib.h>
#endif

// You can define the endian mode in your files, without modifying the SHA1
// source files. Just #define SHA1_LITTLE_ENDIAN or #define SHA1_BIG_ENDIAN
// in your files, before including the SHA1.h header file. If you don't
// define anything, the class defaults to little endian.

#if !defined(SHA1_LITTLE_ENDIAN) && !defined(SHA1_BIG_ENDIAN)
#define SHA1_LITTLE_ENDIAN
#endif

// Same here. If you want variable wiping, #define SHA1_WIPE_VARIABLES, if
// not, #define SHA1_NO_WIPE_VARIABLES. If you don't define anything, it
// defaults to wiping.

#if !defined(SHA1_WIPE_VARIABLES) && !defined(SHA1_NO_WIPE_VARIABLES)
#define SHA1_WIPE_VARIABLES
#endif

/////////////////////////////////////////////////////////////////////////////
// Define 8- and 32-bit variables

#ifndef UINT_32

#ifdef _MSC_VER

#define UINT_8  unsigned __int8
#define UINT_32 unsigned __int32

#else

#define UINT_8 unsigned char

#if (ULONG_MAX == 0xFFFFFFFF)
#define UINT_32 unsigned long
#else
#define UINT_32 unsigned int
#endif

#endif
#endif

/////////////////////////////////////////////////////////////////////////////
// Declare SHA1 workspace

typedef union
{
    UINT_8  c[64];
    UINT_32 l[16];
} SHA1_WORKSPACE_BLOCK;

class CSHA1
{
public:
#ifdef SHA1_UTILITY_FUNCTIONS
    // Two different formats for ReportHash(...)
    enum
    {
        REPORT_HEX = 0,
        REPORT_DIGIT = 1
    };
#endif

    // Constructor and Destructor
    CSHA1();
    ~CSHA1();

    UINT_32 m_state[5];
    UINT_32 m_count[2];
    UINT_32 __reserved1[1];
    UINT_8  m_buffer[64];
    UINT_8  m_digest[20];
    UINT_32 __reserved2[3];

    void Reset();

    // Update the hash value
    void Update(UINT_8 *data, UINT_32 len);
#ifdef SHA1_UTILITY_FUNCTIONS
    bool HashFile(char *szFileName);
#endif

    // Finalize hash and report
    void Final();

    // Report functions: as pre-formatted and raw data
#ifdef SHA1_UTILITY_FUNCTIONS
    void ReportHash(char *szReport, unsigned char uReportType = REPORT_HEX);
#endif
    void GetHash(UINT_8 *puDest);

private:
    // Private SHA-1 transformation
    void Transform(UINT_32 *state, UINT_8 *buffer);

    // Member variables
    UINT_8 m_workspace[64];
    SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above
};

#endif

//----------------------------------------------------------
SHA1.CPP
#include "SHA1.h"

#ifdef SHA1_UTILITY_FUNCTIONS
#define SHA1_MAX_FILE_BUFFER 8000
#endif

// Rotate x bits to the left
#ifndef ROL32
#ifdef _MSC_VER
#define ROL32(_val32, _nBits) _rotl(_val32, _nBits)
#else
#define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits))))
#endif
#endif

#ifdef SHA1_LITTLE_ENDIAN
#define SHABLK0(i) (m_block->l[i] = \
    (ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF))
#else
#define SHABLK0(i) (m_block->l[i])
#endif

#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \
    ^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1))

// SHA-1 rounds
#define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
#define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
#define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); }
#define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); }
#define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); }

CSHA1::CSHA1()
{
    m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace;

    Reset();
}

CSHA1::~CSHA1()
{
    Reset();
}

void CSHA1::Reset()
{
    // SHA1 initialization constants
    m_state[0] = 0x67452301;
    m_state[1] = 0xEFCDAB89;
    m_state[2] = 0x98BADCFE;
    m_state[3] = 0x10325476;
    m_state[4] = 0xC3D2E1F0;

    m_count[0] = 0;
    m_count[1] = 0;
}

void CSHA1::Transform(UINT_32 *state, UINT_8 *buffer)
{
    // Copy state[] to working vars
    UINT_32 a = state[0], b = state[1], c = state[2], d = state[3], e = state[4];

    memcpy(m_block, buffer, 64);

    // 4 rounds of 20 operations each. Loop unrolled.
    _R0(a,b,c,d,e, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3);
    _R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7);
    _R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11);
    _R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15);
    _R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19);
    _R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23);
    _R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27);
    _R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31);
    _R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35);
    _R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39);
    _R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43);
    _R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47);
    _R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51);
    _R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55);
    _R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59);
    _R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63);
    _R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67);
    _R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71);
    _R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75);
    _R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79);

    // Add the working vars back into state
    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
    state[4] += e;

    // Wipe variables
#ifdef SHA1_WIPE_VARIABLES
    a = b = c = d = e = 0;
#endif
}

// Use this function to hash in binary data and strings
void CSHA1::Update(UINT_8 *data, UINT_32 len)
{
    UINT_32 i, j;

    j = (m_count[0] >> 3) & 63;

    if((m_count[0] += len << 3) < (len << 3)) m_count[1]++;

    m_count[1] += (len >> 29);

    if((j + len) > 63)
    {
        i = 64 - j;
        memcpy(&m_buffer[j], data, i);
        Transform(m_state, m_buffer);

        for(; i + 63 < len; i += 64) Transform(m_state, &data[i]);

        j = 0;
    }
    else i = 0;

    memcpy(&m_buffer[j], &data[i], len - i);
}

#ifdef SHA1_UTILITY_FUNCTIONS
// Hash in file contents
bool CSHA1::HashFile(char *szFileName)
{
    unsigned long ulFileSize, ulRest, ulBlocks;
    unsigned long i;
    UINT_8 uData[SHA1_MAX_FILE_BUFFER];
    FILE *fIn;

    if(szFileName == NULL) return false;

    fIn = fopen(szFileName, "rb");
    if(fIn == NULL) return false;

    fseek(fIn, 0, SEEK_END);
    ulFileSize = (unsigned long)ftell(fIn);
    fseek(fIn, 0, SEEK_SET);

    if(ulFileSize != 0)
    {
        ulBlocks = ulFileSize / SHA1_MAX_FILE_BUFFER;
        ulRest = ulFileSize % SHA1_MAX_FILE_BUFFER;
    }
    else
    {
        ulBlocks = 0;
        ulRest = 0;
    }

    for(i = 0; i < ulBlocks; i++)
    {
        fread(uData, 1, SHA1_MAX_FILE_BUFFER, fIn);
        Update((UINT_8 *)uData, SHA1_MAX_FILE_BUFFER);
    }

    if(ulRest != 0)
    {
        fread(uData, 1, ulRest, fIn);
        Update((UINT_8 *)uData, ulRest);
    }

    fclose(fIn); fIn = NULL;
    return true;
}
#endif

void CSHA1::Final()
{
    UINT_32 i;
    UINT_8 finalcount[8];

    for(i = 0; i < 8; i++)
        finalcount[i] = (UINT_8)((m_count[((i >= 4) ? 0 : 1)]
            >> ((3 - (i & 3)) * 8) ) & 255); // Endian independent

    Update((UINT_8 *)"\200", 1);

    while ((m_count[0] & 504) != 448)
        Update((UINT_8 *)"\0", 1);

    Update(finalcount, 8); // Cause a SHA1Transform()

    for(i = 0; i < 20; i++)
    {
        m_digest[i] = (UINT_8)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255);
    }

    // Wipe variables for security reasons
#ifdef SHA1_WIPE_VARIABLES
    i = 0;
    memset(m_buffer, 0, 64);
    memset(m_state, 0, 20);
    memset(m_count, 0, 8);
    memset(finalcount, 0, 8);
    Transform(m_state, m_buffer);
#endif
}

#ifdef SHA1_UTILITY_FUNCTIONS
// Get the final hash as a pre-formatted string
void CSHA1::ReportHash(char *szReport, unsigned char uReportType)
{
    unsigned char i;
    char szTemp[16];

    if(szReport == NULL) return;

    if(uReportType == REPORT_HEX)
    {
        sprintf(szTemp, "%02X", m_digest[0]);
        strcat(szReport, szTemp);

        for(i = 1; i < 20; i++)
        {
            sprintf(szTemp, " %02X", m_digest[i]);
            strcat(szReport, szTemp);
        }
    }
    else if(uReportType == REPORT_DIGIT)
    {
        sprintf(szTemp, "%u", m_digest[0]);
        strcat(szReport, szTemp);

        for(i = 1; i < 20; i++)
        {
            sprintf(szTemp, " %u", m_digest[i]);
            strcat(szReport, szTemp);
        }
    }
    else strcpy(szReport, "Error: Unknown report type!");
}
#endif

// Get the raw message digest
void CSHA1::GetHash(UINT_8 *puDest)
{
    memcpy(puDest, m_digest, 20);
}

 

HMac_SHA1類 

C++版
HMAC_SHA1.H源碼



#ifndef __HMAC_SHA1_H__
#define __HMAC_SHA1_H__

#include "SHA1.h"

typedef unsigned char BYTE ;

class CHMAC_SHA1 : public CSHA1
{
    private:
        BYTE m_ipad[64];
        BYTE m_opad[64];

        char * szReport ;
        char * SHA1_Key ;
        char * AppendBuf1 ;
        char * AppendBuf2 ;


    public:
        
        enum {
            SHA1_DIGEST_LENGTH    = 20,
            SHA1_BLOCK_SIZE        = 64,
            HMAC_BUF_LEN        = 4096
        } ;

        CHMAC_SHA1()
            :szReport(new char[HMAC_BUF_LEN]),
             AppendBuf1(new char[HMAC_BUF_LEN]),
             AppendBuf2(new char[HMAC_BUF_LEN]),
             SHA1_Key(new char[HMAC_BUF_LEN])
        {}

        ~CHMAC_SHA1()
        {
            delete[] szReport ;
            delete[] AppendBuf1 ;
            delete[] AppendBuf2 ;
            delete[] SHA1_Key ;
        }

        void HMAC_SHA1(BYTE *text, int text_len, BYTE *key, int key_len, BYTE *digest);
};


#endif /* __HMAC_SHA1_H__ */

//-------------------------------------------------------
HMAC_SHA1.CPP   code 

//******************************************************************************
//* HMAC_SHA1.cpp : Implementation of HMAC SHA1 algorithm
//*                 Comfort to RFC 2104
//*
//******************************************************************************
#include <iostream>
#include <memory>
#include "HMAC_SHA1.h"


void CHMAC_SHA1::HMAC_SHA1(BYTE *text, int text_len, BYTE *key, int key_len, BYTE *digest)
{
    memset(SHA1_Key, 0, SHA1_BLOCK_SIZE);

    /* repeated 64 times for values in ipad and opad */
    memset(m_ipad, 0x36, sizeof(m_ipad));
    memset(m_opad, 0x5c, sizeof(m_opad));

    /* STEP 1 */
    if (key_len > SHA1_BLOCK_SIZE)  //大於64位
    {
        CSHA1::Reset();
        CSHA1::Update((UINT_8 *)key, key_len);
        CSHA1::Final();

        CSHA1::GetHash((UINT_8 *)SHA1_Key);//20
    }
    else
        memcpy(SHA1_Key, key, key_len);

    /* STEP 2 */
    for (int i=0; i<sizeof(m_ipad); i++)
    {
        m_ipad[i] ^= SHA1_Key[i];        
    }

    /* STEP 3 */
    memcpy(AppendBuf1, m_ipad, sizeof(m_ipad));
    memcpy(AppendBuf1 + sizeof(m_ipad), text, text_len);

    /* STEP 4 */
    CSHA1::Reset();
    CSHA1::Update((UINT_8 *)AppendBuf1, sizeof(m_ipad) + text_len);
    CSHA1::Final();

    CSHA1::GetHash((UINT_8 *)szReport);

    /* STEP 5 */
    for (int j=0; j<sizeof(m_opad); j++)
    {
        m_opad[j] ^= SHA1_Key[j];
    }

    /* STEP 6 */
    memcpy(AppendBuf2, m_opad, sizeof(m_opad));
    memcpy(AppendBuf2 + sizeof(m_opad), szReport, SHA1_DIGEST_LENGTH);

    /*STEP 7 */
    CSHA1::Reset();
    CSHA1::Update((UINT_8 *)AppendBuf2, sizeof(m_opad) + SHA1_DIGEST_LENGTH);
    CSHA1::Final();

    CSHA1::GetHash((UINT_8 *)digest);


//    char * mu;
//    CSHA1::ReportHash(mu,REPORT_HEX);

}

主要控制加密的主要過程

(1) 在密鑰K后面添加0來創建一個子長為B的字符串。(例如,如果K的字長是20
字節,B=60字節,則K后會加入44個零字節0x00)

(2) 將上一步生成的B字長的字符串與ipad做異或運算。

(3) 將數據流text填充至第二步的結果字符串中。

(4) 用H作用於第三步生成的數據流。

(5) 將第一步生成的B字長字符串與opad做異或運算。

(6) 再將第四步的結果填充進第五步的結果中。

(7) 用H作用於第六步生成的數據流,輸出最終結果

涉及到的字符處理

在C/C++環境中,如果需要加密漢字等字符,與Eclipse中產生同樣的加密結果,則需要先將漢字轉化為UTF-8字符,然后進行加密,在經過Base64處理,輸出。

CChineseCode源碼
//--------------------------------------------
// CChineseCode.h
//-------------------------------------------------

#include <string>
#include <stdio.h>
#include <windows.h>
class CChineseCode  
{
public:
    CChineseCode();
    virtual ~CChineseCode();

    // GB2312 轉換成 Unicode
static    void Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer);
    //GB2312 轉為 UTF-8
static    void GB2312ToUTF_8(CString& pOut,char *pText, int pLen);
    //轉16進制
static     BYTE toHex(const BYTE &x);
    // 把Unicode 轉換成 GB2312 
static    void UnicodeToGB2312(char* pOut,unsigned short uData);
    // Unicode 轉換成UTF-8 
static    void UnicodeToUTF_8(char* pOut,WCHAR* pText);
    //URL壓縮
static    CString URLEncode(CString sIn);
    //UTF8壓縮
static    CString   UTF8_Encode(LPTSTR   strUnicode);
    //UTF-8 轉為 GB2312
static    void UTF_8ToGB2312(CString &pOut, char *pText, int pLen);
    // 把UTF-8轉換成Unicode
  static  void UTF_8ToUnicode(WCHAR* pOut,char *pText);

};


//---------------------------------------------
//CChineseCode.cpp
//---------------------------------------------
#include "stdafx.h"
#include "ChineseCode.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CChineseCode::CChineseCode()
{

}

CChineseCode::~CChineseCode()
{

}

// 把UTF-8轉換成Unicode
 void CChineseCode::UTF_8ToUnicode(WCHAR* pOut,char *pText)
 {
 char* uchar = (char *)pOut;

 uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
 uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);

 return;
 }
 // Unicode 轉換成UTF-8 
 void CChineseCode::UnicodeToUTF_8(char* pOut,WCHAR* pText)
 {
 // 注意 WCHAR高低字的順序,低字節在前,高字節在后
char* pchar = (char *)pText;

 pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
 pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
 pOut[2] = (0x80 | (pchar[0] & 0x3F));

 return;
 }
 
// 把Unicode 轉換成 GB2312 
 void CChineseCode::UnicodeToGB2312(char* pOut,unsigned short uData)
 {
 WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(WCHAR),NULL,NULL);
 return;
 }     
 
// GB2312 轉換成 Unicode
 void CChineseCode::Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer)
 {
 ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);
 return;
 }
 
//GB2312 轉為 UTF-8
 void CChineseCode::GB2312ToUTF_8(CString& pOut,char *pText, int pLen)
 {
 char buf[1024];
 char* rst = new char[pLen + (pLen >> 2) + 2];

 memset(buf,0,1024);
 memset(rst,0,pLen + (pLen >> 2) + 2);

 int i = 0;
 int j = 0;      
 while(i < pLen)
 {
 //如果是英文直接復制就可以
if( *(pText + i) >= 0)
{
    rst[j++] = pText[i++];
 }
 else
 {
 WCHAR pbuffer;
 Gb2312ToUnicode(&pbuffer,pText+i);

 UnicodeToUTF_8(buf,&pbuffer);

 unsigned short int tmp = 0;
 tmp = rst[j] = buf[0];
 tmp = rst[j+1] = buf[1];
 tmp = rst[j+2] = buf[2];


 j += 3;
 i += 2;
 }
 }
 strcpy(&rst[j],"\0");

 //返回結果
pOut = rst;             
 delete []rst;   

 return;
 }
 
//UTF-8 轉為 GB2312
 void CChineseCode::UTF_8ToGB2312(CString &pOut, char *pText, int pLen)
 {
 char * newBuf = new char[pLen];
 char Ctemp[4];
 memset(Ctemp,0,4);

 int i =0;
 int j = 0;

 while(i < pLen)
 {
 if(pText[i] > 0)
 {
 newBuf[j++] = pText[i++];                       
 }
 else                 
 {
 WCHAR Wtemp;
 UTF_8ToUnicode(&Wtemp,pText + i);

 UnicodeToGB2312(Ctemp,Wtemp);

 newBuf[j] = Ctemp[0];
 newBuf[j + 1] = Ctemp[1];

 i += 3;    
 j += 2;   
 }
 }
 strcpy(&newBuf[j],"\0");

 pOut = newBuf;
 delete []newBuf;

 return; 
 }
 

CString   CChineseCode::UTF8_Encode(LPTSTR   strUnicode)   
 {   
 long   TLen   ;   
 CString   UTF8_EncodeLong   ;   

 TLen   =   CString(strUnicode).GetLength();   

 if(TLen   ==   0)   
 {   
 return   CString(strUnicode);   
 }   

 long   lngBufferSize   ;   
 long   lngResult   ;   

 //Set   buffer   for   longest   possible   string.   
 lngBufferSize   =   TLen   *   3   +   1   ;   
 char   *bytUtf8   =   new   char[lngBufferSize]   ;   

 //Translate   using   code   page   65001(UTF-8).   

 lngResult   =   WideCharToMultiByte(CP_UTF8,   0,   (unsigned   short*)strUnicode,   TLen,   bytUtf8,   lngBufferSize,   NULL,   0)   ;   

 bytUtf8[lngResult]   =   NULL   ;   

 return   CString(bytUtf8)   ;
 }
 
/*************************************************************************/
 

 BYTE CChineseCode::toHex(const BYTE &x)
{
    return x > 9 ? x + 55: x + 48;
}

CString CChineseCode::URLEncode(CString sIn)
 {
 CString sOut; 
 const int nLen = sIn.GetLength() + 1;
 register LPBYTE pOutTmp = NULL;
 LPBYTE pOutBuf = NULL;
 register LPBYTE pInTmp = NULL;
 LPBYTE pInBuf =(LPBYTE)sIn.GetBuffer(nLen);
 BYTE b = 0;
 //alloc out buffer
 

pOutBuf = (LPBYTE)sOut.GetBuffer(nLen*3 - 2);//new BYTE [nLen  * 3];
 if(pOutBuf)
 {
 pInTmp   = pInBuf;
 pOutTmp = pOutBuf;
 // do encoding
 

while (*pInTmp)
 {
 if(isalnum(*pInTmp))
 *pOutTmp++ = *pInTmp;
 else
 if(isspace(*pInTmp))
 *pOutTmp++ = '+';
 else
 // if(*pInTmp<=127)
 //  *pOutTmp++ = *pInTmp;
 // else
 {
 *pOutTmp++ = '%';

 *pOutTmp++ = toHex(*pInTmp>>4);

 *pOutTmp++ = toHex(*pInTmp%16);
 }

 pInTmp++;

 }
 
*pOutTmp = '\0';

 //sOut=pOutBuf;

 //delete [] pOutBuf;

 sOut.ReleaseBuffer();

 }

 sIn.ReleaseBuffer();

 return sOut;

 }

Base64源碼

Base64源碼
//Base64.h
#include <string>
using namespace std;

class ZBase64
{
public:
    /*編碼
    DataByte
        [in]輸入的數據長度,以字節為單位
    */
    string Encode(const unsigned char* Data,int DataByte);
    /*解碼
    DataByte
        [in]輸入的數據長度,以字節為單位
    OutByte
        [out]輸出的數據長度,以字節為單位,請不要通過返回值計算
        輸出數據的長度
    */
    string Decode(const char* Data,int DataByte,int& OutByte);
};

//-- --Base64.cpp
#include "stdAfx.h"
#include "ZBase64.h"

string ZBase64::Encode(const unsigned char* Data,int DataByte)
{
    //編碼表
    const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    //返回值
    string strEncode;
    unsigned char Tmp[4]={0};
    int LineLength=0;
    for(int i=0;i<(int)(DataByte / 3);i++)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        Tmp[3] = *Data++;
        strEncode+= EncodeTable[Tmp[1] >> 2];
        strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
        strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
        strEncode+= EncodeTable[Tmp[3] & 0x3F];
        if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
    }
    //對剩余數據進行編碼
    int Mod=DataByte % 3;
    if(Mod==1)
    {
        Tmp[1] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
        strEncode+= "==";
    }
    else if(Mod==2)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
        strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
        strEncode+= "=";
    }
    
    return strEncode;
}

string ZBase64::Decode(const char* Data,int DataByte,int& OutByte)
{
    //解碼表
    const char DecodeTable[] =
    {
, 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,
, // '/'
, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
, 0, 0, 0, 0, 0, 0,
, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
, 0, 0, 0, 0, 0,
, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
    };
    //返回值
    string strDecode;
    int nValue;
    int i= 0;
    while (i < DataByte)
    {
        if (*Data != '\r' && *Data!='\n')
        {
            nValue = DecodeTable[*Data++] << 18;
            nValue += DecodeTable[*Data++] << 12;
            strDecode+=(nValue & 0x00FF0000) >> 16;
            OutByte++;
            if (*Data != '=')
            {
                nValue += DecodeTable[*Data++] << 6;
                strDecode+=(nValue & 0x0000FF00) >> 8;
                OutByte++;
                if (*Data != '=')
                {
                    nValue += DecodeTable[*Data++];
                    strDecode+=nValue & 0x000000FF;
                    OutByte++;
                }
            }
            i += 4;
        }
        else// 回車換行,跳過
        {
            Data++;
            i++;
        }
     }
    return strDecode;
}

將“漸入圍城”  字符轉換,經過秘鑰 “123” 加密,再過Base64處理,輸出。

 

 

 

PS:MSDN中,看到了Hmac_sha1加密算法的影子,搞了會沒有搞明白,然后就舍棄了。

 

參考

1、http://www.cnblogs.com/skyaspnet/archive/2010/10/06/1844616.html  DSA算法的理論,實現,以及在破解中的應用

2、http://chenlingreen.iteye.com/blog/91847   Java加密算法

3、http://kb.cnblogs.com/page/166471/ Base 64 Encoding 編碼

4、http://www.iteye.com/topic/604440 HMAC-SHA1的java源代碼實現

5、http://www.cnblogs.com/phinecos/archive/2008/10/10/1308272.html  Base64編解碼(C++版)

6、http://www.codeproject.com/Articles/22118/C-Class-Implementation-of-HMAC-SHA C++ Class Implementation of HMAC-SHA

7、http://www.cnblogs.com/kenkofox/archive/2010/05/10/1731910.html  URL相關編碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM