核心思路就是加密时先随机生成16位向量iv,再将iv和密文拼接后base64encode后输出
解密时前16位是向量iv,剩下是密文。
PHP:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <?php class Aes { protected static $method = 'AES-256-CBC';
public static function encrypt($data, $key) { $ivLen = openssl_cipher_iv_length(static::$method); $iv = openssl_random_pseudo_bytes($ivLen); $text = openssl_encrypt($data, static::$method, $key, OPENSSL_RAW_DATA, $iv); return self::safetyBase64Encode($iv . $text); }
public static function decrypt($text, $key) { $cipherText = self::safetyBase64Decode($text); $ivLen = openssl_cipher_iv_length(static::$method); $iv = substr($cipherText, 0, $ivLen); $cipherText = substr($cipherText, $ivLen); $data = openssl_decrypt($cipherText, static::$method, $key, OPENSSL_RAW_DATA, $iv); return $data; }
public static function safetyBase64Encode($text) { $text = base64_encode($text); $text = str_replace(['+','/'],['-','_'],$text); return $text; }
public static function safetyBase64Decode($text) { $text = str_replace(['-','_'],['+','/'],$text); $text = base64_decode($text); return $text; } }
|
Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; import java.net.URLDecoder;
class Aes { public static String encrypt(String key, String initVector, String value) { try { IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8")); SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES_256/CBC/PKCS5PADDING"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes()); System.out.println("encrypted string: " + Base64.getEncoder().encode(encrypted));
return new String(Base64.getEncoder().encode(encrypted), "UTF-8"); } catch (Exception ex) { ex.printStackTrace(); }
return null; }
public static String decrypt(String key, byte[] initVector, byte[] encrypted) { try { IvParameterSpec iv = new IvParameterSpec(initVector); SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES_256/CBC/PKCS5PADDING"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(encrypted);
return new String(original, "UTF-8"); } catch (Exception ex) { ex.printStackTrace(); }
return null; }
public static void main(String[] args) { String encryptString = args[0]; String key = "abcdabcdabcdabcdabcdabcdabcdabcd";
try { encryptString = URLDecoder.decode(encryptString, "utf-8"); encryptString = encryptString.replace("-", "+").replace("_", "/");
byte[] encryptBytes = Base64.getDecoder().decode(encryptString); byte[] ivBytes = new byte[16]; byte[] cipherBytes = new byte[encryptBytes.length - 16];
System.arraycopy(encryptBytes, 0, ivBytes, 0, 16); System.arraycopy(encryptBytes, 16, cipherBytes, 0, encryptBytes.length - 16);
String raw = decrypt(key, ivBytes, cipherBytes); System.out.println(raw); } catch (Exception ex) { ex.printStackTrace(); } } }
|
Golang:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| package main
import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "errors" "fmt" "io" )
//填充 func pad(src []byte) []byte { padding := aes.BlockSize - len(src)%aes.BlockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(src, padtext...) }
func unpad(src []byte) ([]byte, error) { length := len(src) unpadding := int(src[length-1])
if unpadding > length { return nil, errors.New("unpad error. This could happen when incorrect encryption key is used") }
return src[:(length - unpadding)], nil }
func encrypt(key []byte, text string) (string, error) { block, err := aes.NewCipher(key) if err != nil { return "", err }
msg := pad([]byte(text)) ciphertext := make([]byte, aes.BlockSize+len(msg))
//随机生成向量 iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return "", err }
mode := cipher.NewCBCEncrypter(block, iv) mode.CryptBlocks(ciphertext[aes.BlockSize:], msg) finalMsg := (base64.StdEncoding.EncodeToString(ciphertext))
return finalMsg, nil }
func decrypt(key []byte, text string) (string, error) { block, err := aes.NewCipher(key) if err != nil { return "", err }
decodedMsg, err := base64.StdEncoding.DecodeString((text))
if err != nil { return "", err }
if (len(decodedMsg) % aes.BlockSize) != 0 { return "", errors.New("blocksize must be multipe of decoded message length") }
iv := decodedMsg[:aes.BlockSize] msg := decodedMsg[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(msg, msg)
unpadMsg, err := unpad(msg) if err != nil { return "", err }
return string(unpadMsg), nil }
func main() { key := []byte("abcdabcdabcdabcdabcdabcdabcdabcd") encryptText, _ := encrypt(key, "hello")
fmt.Printf("encrypt text is %s \n", encryptText)
rawText, err := decrypt(key, encryptText) if err != nil { fmt.Println(err) return }
fmt.Printf("raw text is %s \n", rawText) }
|