簡介:java服務端負責解密go和c語言產生得加密數據,這裏採用aes得ECB加密模式
java端得代碼如下:
package com.example.demo;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES {
public static byte[] encrypt(String key, byte[] origData) throws GeneralSecurityException {
byte[] keyBytes = getKeyBytes(key);
byte[] buf = new byte[16];
System.arraycopy(keyBytes, 0, buf, 0, keyBytes.length > buf.length ? keyBytes.length : buf.length);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(buf, "AES"), new IvParameterSpec(keyBytes));
return cipher.doFinal(origData);
}
public static byte[] decrypt(String key, byte[] crypted) throws GeneralSecurityException {
byte[] keyBytes = getKeyBytes(key);
byte[] buf = new byte[16];
System.arraycopy(keyBytes, 0, buf, 0, keyBytes.length > buf.length ? keyBytes.length : buf.length);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), new IvParameterSpec(keyBytes));
return cipher.doFinal(crypted);
}
private static byte[] getKeyBytes(String key) {
byte[] bytes = key.getBytes();
return bytes.length == 16 ? bytes : Arrays.copyOf(bytes, 16);
}
public static String encrypt(String key, String val) throws GeneralSecurityException {
byte[] origData = val.getBytes();
byte[] crypted = encrypt(key, origData);
return Base64.getEncoder().encodeToString(crypted);
}
public static String decrypt(String key, String val) throws GeneralSecurityException {
byte[] crypted= Base64.getDecoder().decode(val);
byte[] origData = decrypt(key, crypted);
return new String(origData);
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String key = "HelloWorld123456";
String content = "t0EMsCSB7wwDxlaWnwj23w==";
System.out.println(decrypt(key, content));
}
}
C語言客戶端得代碼如下:
/**
build with shell:
gcc -Wall aes.c -lcrypto -o aes
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
void encrypt(unsigned char* in, int inl, unsigned char *out, int* len, unsigned char * key){
unsigned char iv[8];
EVP_CIPHER_CTX ctx;
//此init做的僅是將ctx內存 memset爲0
EVP_CIPHER_CTX_init(&ctx);
//cipher = EVP_aes_128_ecb();
//原型爲int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv)
//另外對於ecb電子密碼本模式來說,各分組獨立加解密,前後沒有關係,也用不着iv
EVP_EncryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, key, iv);
*len = 0;
int outl = 0;
//這個EVP_EncryptUpdate的實現實際就是將in按照inl的長度去加密,實現會取得該cipher的塊大小(對aes_128來說是16字節)並將block-size的整數倍去加密。
//如果輸入爲50字節,則此處僅加密48字節,outl也爲48字節。輸入in中的最後兩字節拷貝到ctx->buf緩存起來。
//對於inl爲block_size整數倍的情形,且ctx->buf並沒有以前遺留的數據時則直接加解密操作,省去很多後續工作。
EVP_EncryptUpdate(&ctx, out+*len, &outl, in+*len, inl);
*len+=outl;
//餘下最後n字節。此處進行處理。
//如果不支持pading,且還有數據的話就出錯,否則,將block_size-待處理字節數個數個字節設置爲此個數的值,如block_size=16,數據長度爲4,則將後面的12字節設置爲16-4=12,補爲一個分組後加密
//對於前面爲整分組時,如輸入數據爲16字節,最後再調用此Final時,不過是對16個0進行加密,此密文不用即可,也根本用不着調一下這Final。
int test = inl>>4;
if(inl != test<<4){
EVP_EncryptFinal_ex(&ctx,out+*len,&outl);
*len+=outl;
}
EVP_CIPHER_CTX_cleanup(&ctx);
}
void decrypt(unsigned char* in, int inl, unsigned char *out, unsigned char *key){
unsigned char iv[8];
EVP_CIPHER_CTX ctx;
//此init做的僅是將ctx內存 memset爲0
EVP_CIPHER_CTX_init(&ctx);
//cipher = EVP_aes_128_ecb();
//原型爲int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv)
//另外對於ecb電子密碼本模式來說,各分組獨立加解密,前後沒有關係,也用不着iv
EVP_DecryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, key, iv);
int len = 0;
int outl = 0;
EVP_DecryptUpdate(&ctx, out+len, &outl, in+len, inl);
len += outl;
EVP_DecryptFinal_ex(&ctx, out+len, &outl);
len+=outl;
out[len]=0;
EVP_CIPHER_CTX_cleanup(&ctx);
}
#define MAX_BUF_LEN 8192
int main(int argc, char **argv)
{
unsigned char content[MAX_BUF_LEN]; //待加密得字符串
unsigned char key[] = "HelloWorld123456"; //加密得key,長度爲固定長度16
unsigned char en[MAX_BUF_LEN],de[MAX_BUF_LEN],base64[MAX_BUF_LEN], base64_out[MAX_BUF_LEN];
int len;
memset(content, 0,MAX_BUF_LEN);
memset(en, 0, MAX_BUF_LEN);
memset(de, 0, MAX_BUF_LEN);
memset(base64, 0,MAX_BUF_LEN);
memset(base64_out, 0, MAX_BUF_LEN);
//strcpy(content, "HelloHbnfjkwahgruiep");
strcpy(content, "我分解機");
printf("%d %s\n", strlen((const char*)content), content);
encrypt(content,strlen((const char*)content), en, &len, key);
int encode_str_size = EVP_EncodeBlock(base64, en, len);
printf("%d %s\n", encode_str_size, base64);
int length = EVP_DecodeBlock(base64_out, base64, strlen((const char*)base64));
//EVP_DecodeBlock內部同樣調用EVP_DecodeInit + EVP_DecodeUpdate + Evp_DecodeFinal實現,但是並未處理尾部的'='字符,因此結果字符串長度總是爲3的倍數
while(base64[--encode_str_size] == '=') length--;
decrypt(base64_out, length, de, key);
printf("%d %s\n", strlen((const char*)de), de);
return 0;
}
go客戶端得代碼如下:
package main
import (
"crypto/aes"
"encoding/base64"
"encoding/hex"
"log"
"os"
)
func main() {
argc := len(os.Args)
if argc !=3 {
os.Stdout.WriteString("argc is not 3\n")
return
}
//origData := []byte("Hello World") // 待加密的數據
origData := []byte(os.Args[2]) // 待加密的數據
//key := []byte("1234567812345678") // 加密的密鑰
key := []byte(os.Args[1]) // 加密的密鑰
log.Println("密鑰", string(key))
log.Println("原文:", string(origData))
log.Println("------------------ ECB模式 --------------------")
encrypted := AesEncryptECB(origData, key)
log.Println("密文(hex):", hex.EncodeToString(encrypted))
log.Println("密文(base64):", base64.StdEncoding.EncodeToString(encrypted))
decrypted := AesDecryptECB(encrypted, key)
log.Println("解密結果:", string(decrypted))
}
// =================== ECB ======================
func AesEncryptECB(origData []byte, key []byte) (encrypted []byte) {
cipher, _ := aes.NewCipher(generateKey(key))
length := (len(origData) + aes.BlockSize) / aes.BlockSize
plain := make([]byte, length*aes.BlockSize)
copy(plain, origData)
pad := byte(len(plain) - len(origData))
for i := len(origData); i < len(plain); i++ {
plain[i] = pad
}
encrypted = make([]byte, len(plain))
// 分組分塊加密
for bs, be := 0, cipher.BlockSize(); bs <= len(origData); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
func AesDecryptECB(encrypted []byte, key []byte) (decrypted []byte) {
cipher, _ := aes.NewCipher(generateKey(key))
decrypted = make([]byte, len(encrypted))
//
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
func generateKey(key []byte) (genKey []byte) {
genKey = make([]byte, 16)
copy(genKey, key)
for i := 16; i < len(key); {
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
genKey[j] ^= key[i]
}
}
return genKey
}