AES对称加密例子

原文地址http://java.sun.com/developer/technicalArticles/Security/AES/AES_v1.html
2000年9月开始,nist开始支持fips,来取代已经过时的des(Data Enryption Strandard).

1 什么是AES
AES是一种对称的私钥加密技术。它支持128,192,256位加密。


2 AES和Java
从j2se1.4.2开始,集成了JCE包。
现在的java支持128位key的加密。(下面的程序也是以128位为例讲解的)


3 如何使用JCE


import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;

/**
* This program generates a AES key, retrieves its raw bytes, and
* then reinstantiates a AES key from the key bytes.
* The reinstantiated key is used to initialize a AES cipher for
* encryption and decryption.
*/

public class AES {

/**
* Turns array of bytes into string
*
* @param buf Array of bytes to convert to hex string
* @return Generated hex string
*/
public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;

for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");

strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}

return strbuf.toString();
}

public static void main(String[] args) throws Exception {

String message="This is just an example";

// Get the KeyGenerator

KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available


// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");


// Instantiate the cipher

Cipher cipher = Cipher.getInstance("AES");

cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

byte[] encrypted =
cipher.doFinal((args.length == 0 ?
"This is just an example" : args[0]).getBytes());
System.out.println("encrypted string: " + asHex(encrypted));

cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] original =
cipher.doFinal(encrypted);
String originalString = new String(original);
System.out.println("Original string: " +
originalString + " " + asHex(original));
}
}



4 更强壮的加密
kgen.init(256); // 128 and 192 bits also available
按照原文提示的地址可以更新下一个包,然后稍微修改下加密位数就可以了。不过jdk1.4默认只支持128位的加密,实际上,作者也建议同时利用SSL,比单独一味强调加密位数效果要好。
5 同时使用SSL和AES

server端





import java.io.*;
import java.security.*;
import javax.net.ssl.*;


import java.util.regex.*;


public class HelloServerSSL {
public static void main(String[] args) {
SSLServerSocket s;


// Pick all AES algorithms of 256 bits key size
String patternString = "AES.*256";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher;
boolean matchFound;

try {
SSLServerSocketFactory sslSrvFact =
(SSLServerSocketFactory)
SSLServerSocketFactory.getDefault();
s =(SSLServerSocket)sslSrvFact.createServerSocket(8181);

SSLSocket in = (SSLSocket)s.accept();


String str[]=in.getSupportedCipherSuites();

int len = str.length;
String set[] = new String[len];

int j=0, k = len-1;
for (int i=0; i < len; i++) {

// Determine if pattern exists in input
matcher = pattern.matcher(str[i]);
matchFound = matcher.find();

if (matchFound)
set[j++] = str[i];
else
set[k--] = str[i];
}

in.setEnabledCipherSuites(set);

str=in.getEnabledCipherSuites();

System.out.println("Available Suites after Set:");
for (int i=0; i < str.length; i++)
System.out.println(str[i]);
System.out.println("Using cipher suite: " +
(in.getSession()).getCipherSuite());

PrintWriter out = new PrintWriter (in.getOutputStream(),
true);
out.println("Hello on a SSL socket");
in.close();
} catch (Exception e) {
System.out.println("Exception" + e);
}
}
}




client端




import java.io.*;
import java.security.*;
import javax.net.ssl.*;


import java.util.regex.*;


public class HelloClientSSL {
public static void main(String[] args) {


// Pick all AES algorithms of 256 bits key size
String patternString = "AES.*256";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher;
boolean matchFound;

try {

SSLSocketFactory sslFact =
(SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket s =
(SSLSocket)sslFact.createSocket(args.length == 0 ?
"127.0.0.1" : args[0], 8181);

String str[]=s.getSupportedCipherSuites();

int len = str.length;
String set[] = new String[len];

int j=0, k = len-1;
for (int i=0; i < len; i++) {
System.out.println(str[i]);

// Determine if pattern exists in input
matcher = pattern.matcher(str[i]);
matchFound = matcher.find();

if (matchFound)
set[j++] = str[i];
else
set[k--] = str[i];
}

s.setEnabledCipherSuites(set);

str=s.getEnabledCipherSuites();

System.out.println("Available Suites after Set:");
for (int i=0; i < str.length; i++)
System.out.println(str[i]);

OutputStream out = s.getOutputStream();
BufferedReader in = new BufferedReader (
new InputStreamReader(s.getInputStream()));

String mesg = in.readLine();
System.out.println("Socket message: " + mesg);
in.close();
} catch (Exception e) {
System.out.println("Exception" + e);
}
}
}





运行结果

Available Suites after Set:TLS_RSA_WITH_AES_256_CBC_SHATLS_DHE_RSA_WITH_AES_256_CBC_SHATLS_DHE_DSS_WITH_AES_256_CBC_SHATLS_DH_anon_WITH_AES_256_CBC_SHASSL_DH_anon_EXPORT_WITH_DES40_CBC_SHASSL_DH_anon_EXPORT_WITH_RC4_40_MD5SSL_DH_anon_WITH_DES_CBC_SHASSL_DH_anon_WITH_3DES_EDE_CBC_SHATLS_DH_anon_WITH_AES_128_CBC_SHASSL_DH_anon_WITH_RC4_128_MD5SSL_RSA_WITH_NULL_SHASSL_RSA_WITH_NULL_MD5SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHASSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHASSL_RSA_EXPORT_WITH_DES40_CBC_SHASSL_RSA_EXPORT_WITH_RC4_40_MD5SSL_DHE_DSS_WITH_DES_CBC_SHASSL_DHE_RSA_WITH_DES_CBC_SHASSL_RSA_WITH_DES_CBC_SHASSL_DHE_DSS_WITH_3DES_EDE_CBC_SHASSL_DHE_RSA_WITH_3DES_EDE_CBC_SHASSL_RSA_WITH_3DES_EDE_CBC_SHATLS_DHE_DSS_WITH_AES_128_CBC_SHATLS_DHE_RSA_WITH_AES_128_CBC_SHATLS_RSA_WITH_AES_128_CBC_SHASSL_RSA_WITH_RC4_128_SHASSL_RSA_WITH_RC4_128_MD5Using cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA


别人的例子




/**
*PrivateExmaple.java
*Copyright 2005-2-16
*/
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;

/**
*˽?¼ÓÃÜ&&±&Ö¤Ï&Ï&&uÃÜÐÔ
*/
public class PrivateExample{
public static void main(String[] args) throws Exception{

byte[] plainText="12345678".getBytes();

//Í‥¹&KeyGeneratorÐγÉÒ&&&key
System.out.println("\nStart generate AES key");
KeyGenerator keyGen=KeyGenerator.getInstance("AES");
keyGen.init(128);
Key key=keyGen.generateKey();
System.out.println("Finish generating AES key");

//&&&ÃÒ&&&˽?¼ÓÃÜÀaCipher&&ECBÊǼÓÃÜ·½Ê½&&PKCS5PaddingÊÇÌ&³&·½·‥
Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");
System.out.println("\n"+cipher.getProvider().getInfo());

//ʹÓÃ˽?¼ÓÃÜ
System.out.println("\nStart encryption:");
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[] cipherText=cipher.doFinal(plainText);
System.out.println("Finish encryption:");
System.out.println(new String(cipherText,"UTF8"));

System.out.println("\nStart decryption:");
cipher.init(Cipher.DECRYPT_MODE,key);
byte[] newPlainText=cipher.doFinal(cipherText);
System.out.println("Finish decryption:");

System.out.println(new String(newPlainText,"UTF8"));
}
}



自己稍加修改的例子


byte[] plainText="12345678".getBytes();

//Í‥¹&KeyGeneratorÐγÉÒ&&&key
System.out.println("\nStart generate AES key");
KeyGenerator keyGen=KeyGenerator.getInstance("AES");

String pwd = "passord";
keyGen.init(128, new SecureRandom(pwd.getBytes()));
//keyGen.init(128);

//Key key=keyGen.generateKey();
SecretKey skey = keyGen.generateKey();
byte[] raw = skey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

System.out.println("Finish generating AES key");

//&&&ÃÒ&&&˽?¼ÓÃÜÀaCipher&&ECBÊǼÓÃÜE½Ê½&&PKCS5PaddingÊÇÌ&³&E½E‥
Cipher cipher=Cipher.getInstance("AES");
System.out.println("\n"+cipher.getProvider().getInfo());

//ʹÓÃ˽?¼ÓÃÜ
System.out.println("\nStart encryption:");
cipher.init(Cipher.ENCRYPT_MODE,skeySpec);

byte[] cipherText=cipher.doFinal(plainText);
System.out.println("Finish encryption:");
System.out.println(new String(cipherText,"UTF8"));

System.out.println("\nStart decryption:");
cipher.init(Cipher.DECRYPT_MODE,skeySpec);
byte[] newPlainText=cipher.doFinal(cipherText);
System.out.println("Finish decryption:");

System.out.println(new String(newPlainText,"UTF8"));
}
### Python中AES对称加密算法的实现及使用 在Python中,可以通过`pycryptodome`库来实现AES对称加密算法。该库提供了多种加密模式的支持,例如ECB和CBC模式。下面详细介绍如何使用Python中的AES对称加密。 #### 安装依赖库 为了使用AES加密功能,需先安装`pycryptodome`库: ```bash pip install pycryptodome ``` #### AES CBC模式下的加密与解密 CBC(Cipher Block Chaining)模式是AES常用的一种工作模式,在这种模式下,每个明文块都会与前一个密文块进行异或操作后再加密。因此,CBC模式需要初始化向量(IV),即偏移量[^2]。 ##### 实现代码 以下是一个完整的AES CBC模式加密与解密的例子: ```python from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from Crypto.Random import get_random_bytes def aes_encrypt(data, key): """ 使用AES-CBC模式加密数据 """ cipher = AES.new(key, AES.MODE_CBC) # 创建AES对象并指定为CBC模式 padded_data = pad(data.encode(), AES.block_size) # 对数据进行填充以满足块大小的要求 ct_bytes = cipher.encrypt(padded_data) # 执行加密 return cipher.iv + ct_bytes # 返回IV加上加密后的数据以便后续解密 def aes_decrypt(encrypted_data, key): """ 使用AES-CBC模式解密数据 """ iv = encrypted_data[:AES.block_size] # 提取IV ct = encrypted_data[AES.block_size:] # 获取实际加密部分的数据 cipher = AES.new(key, AES.MODE_CBC, iv) # 初始化AES对象用于解密 pt = unpad(cipher.decrypt(ct), AES.block_size) # 解密并去除填充 return pt.decode() # 将字节串转换回字符串形式 # 示例运行 key = get_random_bytes(16) # 随机生成16字节的密钥 data = "Hello, World!" encrypted_data = aes_encrypt(data, key) print(f"Encrypted Data: {encrypted_data}") decrypted_data = aes_decrypt(encrypted_data, key) print(f"Decrypted Data: {decrypted_data}") ``` 此代码片段展示了如何通过`Crypto.Cipher.AES`模块完成加密和解密的过程,并且包含了必要的填充处理逻辑[^2]。 #### 填充方式的选择 当原始消息长度不符合AES规定的块大小时,通常会采用某种填充策略使数据达到合适的长度。常见的填充方法有Zero Padding、PKCS5 Padding以及PKCS7 Padding等。其中,PKCS7 Padding是最推荐的方式之一,因为它能够适应任意块大小的情况[^4]。 对于上述例子而言,默认采用了PKCS7 Padding来进行数据补齐操作;而在某些特定场景下也可以手动调整填充规则或者选用其他类型的填充机制。 #### ECB模式简介及其局限性 除了CBC之外,另一种较为简单的AES运作模式便是ECB(Electronic Codebook)。然而需要注意的是,由于ECB不具备扩散特性——相同输入总是会产生相同的输出结果——所以它并不适合保护敏感信息的安全传输需求[^1]。 尽管如此,在一些低风险环境下仍然可能见到它的身影。不过一般建议优先考虑更安全可靠的选项比如GCM(Galois/Counter Mode),因为后者不仅提供认证保障还能有效防止篡改攻击的发生。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值