工具:
-
crypto python 提供的加密库
-
python 2.7.10
本文采用 AES 对文件进行加密,采用CBC模式
因为 AES 是块加密,每 16 字节进行一次加密
采用 lambda 实现对文件分块,不足 16 字节 的用 空格补齐。
代码如下:
#! -*- coding:utf-8 -*-
from Crypto.Cipher import AES
import random
import string
from Crypto import Random
import binascii
import sys
import re
from binascii import b2a_hex, a2b_hex
PADDING = '\0'
pad_it = lambda s: s+(16 - len(s)%16)*PADDING
# iv 是AES加密的初始密钥向量 key 是密钥
# 加密函数
def string_normal(s,key,iv):
s = pad_it(s)
cryptor = AES.new(key,AES.MODE_CBC,iv)
sum = ''
# 加密的内容必须是16的倍数,如果不是就用pad_it() 函数补全
for ii in range(len(s)/16):
sum = sum + b2a_hex(cryptor.encrypt(s[ii*16:ii*16+16]))
#因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
#所以这里统一把加密后的字符串转化为16进制字符串
return sum
# 解密
def decrypt(text,key,iv):
cryptor = AES.new(key,AES.MODE_CBC, iv)
#将 16进制字符串转化为二进制字符串再进行解密
plain_text = cryptor.decrypt(a2b_hex(text))
return plain_text
由于采用的是 生成的密钥是 16 位,所以采用随机生成 16 位的密钥信息, 代码如下:
"""
生成长度16的随机数密码
"""
def gen_random_key(length):
# 随机出数字的个数
numOfNum = random.randint(1,length-1)
numOfLetter = length - numOfNum
# 选中numOfNum个数字
selectNum = [random.choice(string.digits) for i in range(numOfNum)]
# 选中numOfLetter个字母
selectLetter = [random.choice(string.ascii_letters) for i in range(numOfLetter)]
# 打乱这个组合
slcChar = selectNum + selectLetter
random.shuffle(slcChar)
# 生成密码
genKey = ''.join([i for i in slcChar])
return genKey
使用 python 加密 ,java 解密代码如下:
package com.ben.restjpademo;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.junit.Test;
import sun.misc.BASE64Decoder;
import com.ben.restjpademo.dao.JobRepository;
import com.ben.restjpademo.dao.JobspiderReposity;
import com.ben.restjpademo.dao.KeymngRepository;
import com.ben.restjpademo.domain.Job;
import com.ben.restjpademo.domain.Keymng;
import javax.xml.bind.DatatypeConverter;
public class TestHadoop {
/*
* 20170601 读取hadoop中的文件
*/
@Test
public void getfile() throws IOException{
String uri = "hdfs://192.168.17.30:9000";
Configuration config = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri),config);
// 列出 hdfs 上的 /source 目录下的所有文件和目录
FileStatus[] statuses = fs.listStatus(new Path("/source"));
for(FileStatus status : statuses){
System.out.println(status);
}
// 显示在 hdfs 上/source下指定文件的内容
OutputStream os = new ByteArrayOutputStream();
String content = "";
InputStream is = fs.open(new Path("/source/www.sina.com.cn/www.sina.com.cn.txt"));
IOUtils.copyBytes(is,os,1024, true);
content = os.toString();
byte[] b = content.getBytes();
# 将 python 加密的 16 进制字符串转化为 2 进制
byte[] bytes = DatatypeConverter.parseHexBinary(content);
System.out.println("加密文件:");
System.out.println(content.length());
System.out.println(bytes);
this.padding(bytes);
}
public void padding(byte[] s){
String key = "XCwX56kd6AYAhnlc";
String iv = "KnYpyHyGJtR5nFkx";
try{
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(s);
String originalString = new String(original);
System.out.println("解密文件:");
System.out.println(originalString);
FileOutputStream out = null;
try{
out = new FileOutputStream(new File("E:/storge.html"));
out.write(originalString.getBytes());
out.close();
}catch(IOException e){
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
}
}