当前位置:首页 » 密码管理 » javasalt加密

javasalt加密

发布时间: 2024-07-21 01:45:29

A. 常见密码算法原理

PBKDF2(Password-Based Key Derivation Function)是一个用来导出密钥的函数,用来生成加密的密码,增加破解的难度,类似bcrypt/scrypt等,可以用来进行密码或者口令的加密存储。主要是盐值+pwd,经过多轮HMAC算法的计算,产生的密文。
PBKDF2函数的定义
DK = PBKDF2(PRF, Password, Salt, c, dkLen)
• PRF是一个伪随机函数,例如HASH_HMAC函数,它会输出长度为hLen的结果。
• Password是用来生成密钥的原文密码。
• Salt是一个加密用的盐值。
• c是进行重复计算的次数。
• dkLen是期望得到的密钥的长度。
• DK是最后产生的密钥。
https://segmentfault.com/a/1190000004261009

下面我们以Alice和Bob为例叙述Diffie-Hellman密钥交换的原理。
1,Diffie-Hellman交换过程中涉及到的所有参与者定义一个组,在这个组中定义一个大质数p,底数g。
2,Diffie-Hellman密钥交换是一个两部分的过程,Alice和Bob都需要一个私有的数字a,b。
下面是DH交换的过程图:
本图片来自wiki
下面我们进行一个实例
1.爱丽丝与鲍伯协定使用p=23以及g=5.
2.爱丽丝选择一个秘密整数a=6, 计算A = g^a mod p并发送给鲍伯。
A = 5^6 mod 23 = 8.
3.鲍伯选择一个秘密整数b=15, 计算B = g^b mod p并发送给爱丽丝。
B = 5^15 mod 23 = 19.
4.爱丽丝计算s = B a mod p
19^6 mod 23 = 2.
5.鲍伯计算s = A b mod p
8^15 mod 23 = 2.

ECDH:
ECC算法和DH结合使用,用于密钥磋商,这个密钥交换算法称为ECDH。交换双方可以在不共享任何秘密的情况下协商出一个密钥。ECC是建立在基于椭圆曲线的离散对数问题上的密码体制,给定椭圆曲线上的一个点P,一个整数k,求解Q=kP很容易;给定一个点P、Q,知道Q=kP,求整数k确是一个难题。ECDH即建立在此数学难题之上。密钥磋商过程:
假设密钥交换双方为Alice、Bob,其有共享曲线参数(椭圆曲线E、阶N、基点G)。

来自 http://www.cnblogs.com/fishou/p/4206451.html

https://zh.wikipedia.org/wiki/SHA%E5%AE%B6%E6%97%8F

exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
-----END RSA PRIVATE KEY-----
while a RSA public key contains only the following data:
-----BEGIN RSA PUBLIC KEY-----
RSAPublicKey ::= SEQUENCE {
molus INTEGER, -- n
publicExponent INTEGER -- e
}
-----END RSA PUBLIC KEY-----
and this explains why the private key block is larger.
Note that a more standard format for non-RSA public keys is
-----BEGIN PUBLIC KEY-----
PublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
PublicKey BIT STRING
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
-----END PUBLIC KEY-----
More info here.
BTW, since you just posted a screenshot of the private key I strongly hope it was just for tests :)

密钥的长度
C:\herong>java RsaKeyGenerator 128
p: 17902136406704537069
q: 17902136406704537077
m:
Molus:
Key size: 128
Public key:
Private key:
C:\herong>java RsaKeyGenerator 256
p:
q:
m: ...
Molus: ...
Key size: 256
Public key: ...
Private key: ...

https://security.stackexchange.com/questions/90169/rsa-public-key-and-private-key-lengths
https://stackoverflow.com/questions/2921508/trying-to-understand-java-rsa-key-size >

http://www.herongyang.com/Cryptography/RSA-BigInteger-Keys-Generated-by-RsaKeyGenerator-java.html

update() adds data to the Cipher’s internal buffer, then returns all currently completely encoded blocks. If there are any encoded blocks left over, they remain in the Cipher’s buffer until the next call, or a call to doFinal(). This means that if you call update() with a four byte array to encrypt, and the buffer size is eight bytes, you will not receive encoded data on the return (you’ll get a null instead). If your next call to update() passes five bytes of data in, you will get an 8 byte (the block size) array back, containing the four bytes passed in on the previous call, the first four bytes from the current call – the remaining byte from the current call is left in the Cipher’s buffer.
doFinal() on the other hand is much simpler: it encrypts the passed data, pads it out to the necessary length, and then returns it. The Cipher is essentially stateless.

来自 https://segmentfault.com/a/1190000006931511

DH算法的中间人攻击
在最初的描述中,迪菲-赫尔曼密钥交换本身并没有提供通讯双方的身份验证服务,因此它很容易受到中间人攻击。 一个中间人在信道的中央进行两次迪菲-赫尔曼密钥交换,一次和Alice另一次和Bob,就能够成功的向Alice假装自己是Bob,反之亦然。而攻击者可以解密(读取和存储)任何一个人的信息并重新加密信息,然后传递给另一个人。因此通常都需要一个能够验证通讯双方身份的机制来防止这类攻击。

优缺点:
1、 仅当需要时才生成密钥,减小了将密钥存储很长一段时间而致使遭受攻击的机会。
2、 除对全局参数的约定外,密钥交换不需要事先存在的基础结构。
然而,该技术也存在许多不足:
1、 没有提供双方身份的任何信息。
2、 它是计算密集性的,因此容易遭受阻塞性攻击,即对手请求大量的密钥。受攻击者花费了相对多的计算资源来求解无用的幂系数而不是在做真正的工作。
3、 没办法防止重演攻击。
4、 容易遭受中间人的攻击。第三方C在和A通信时扮演B;和B通信时扮演A。A和B都与C协商了一个密钥,然后C就可以监听和传递通信量。中间人的攻击按如下进行:
(1) B在给A的报文中发送他的公开密钥。
(2) C截获并解析该报文。C将B的公开密钥保存下来并给A发送报文,该报文具有B的用户ID但使用C的公开密钥YC,仍按照好像是来自B的样子被发送出去。A收到C的报文后,将YC和B的用户ID存储在一块。类似地,C使用YC向B发送好像来自A的报文。
(3) B基于私有密钥XB和YC计算秘密密钥K1。A基于私有密钥XA和YC计算秘密密钥K2。C使用私有密钥XC和YB计算K1,并使用XC和YA计算K2。
(4) 从现在开始,C就可以转发A发给B的报文或转发B发给A的报文,在途中根据需要修改它们的密文。使得A和B都不知道他们在和C共享通信。

B. java如何实现md5加密的压缩为zip

public class ZipUtil {
private static final String ALGORITHM = "PBEWithMD5AndDES";
private static Logger logger = Logger.getLogger(ZipUtil.class);
public static void zip(String zipFileName, String inputFile,String pwd) throws Exception {
zip(zipFileName, new File(inputFile), pwd);
}

/**
* 功能描述:压缩指定路径下的所有文件
* @param zipFileName 压缩文件名(带有路径)
* @param inputFile 指定压缩文件夹
* @return
* @throws Exception
*/
public static void zip(String zipFileName, String inputFile) throws Exception {
zip(zipFileName, new File(inputFile), null);
}
/**
* 功能描述:压缩文件对象
* @param zipFileName 压缩文件名(带有路径)
* @param inputFile 文件对象
* @return
* @throws Exception
*/
public static void zip(String zipFileName, File inputFile,String pwd) throws Exception {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
zip(out, inputFile, "",pwd);
out.close();
}
/**
*
* @param out 压缩输出流对象
* @param file
* @param base
* @throws Exception
*/
public static void zip(ZipOutputStream outputStream, File file, String base,String pwd) throws Exception {
if (file.isDirectory()) {
File[] fl = file.listFiles();
outputStream.putNextEntry(new ZipEntry(base + "/"));
base = base.length() == 0 ? "" : base + "/";
for (int i = 0; i < fl.length; i++) {
zip(outputStream, fl[i], base + fl[i].getName(), pwd);
}
}
else {
outputStream.putNextEntry(new ZipEntry(base));
FileInputStream inputStream = new FileInputStream(file);
//普通压缩文件
if(pwd == null || pwd.trim().equals("")){
int b;
while ((b = inputStream.read()) != -1){
outputStream.write(b);
}
inputStream.close();
}
//给压缩文件加密
else{
PBEKeySpec keySpec = new PBEKeySpec(pwd.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey passwordKey = keyFactory.generateSecret(keySpec);
byte[] salt = new byte[8];
Random rnd = new Random();
rnd.nextBytes(salt);
int iterations = 100;
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, passwordKey, parameterSpec);
outputStream.write(salt);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null){
outputStream.write(output);
}
}
byte[] output = cipher.doFinal();
if (output != null){
outputStream.write(output);
}
inputStream.close();
outputStream.flush();
outputStream.close();
}
}
file.delete();
}

public static void unzip(String zipFileName, String outputDirectory)throws Exception {
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(zipFileName));
unzip(inputStream, outputDirectory, null);
}

/**
* 功能描述:将压缩文件解压到指定的文件目录下
* @param zipFileName 压缩文件名称(带路径)
* @param outputDirectory 指定解压目录
* @return
* @throws Exception
*/
public static void unzip(String zipFileName, String outputDirectory, String pwd)throws Exception {
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(zipFileName));
unzip(inputStream, outputDirectory, pwd);
}

public static void unzip(File zipFile, String outputDirectory, String pwd)throws Exception {
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(zipFile));
unzip(inputStream, outputDirectory,pwd);
}

public static void unzip(ZipInputStream inputStream, String outputDirectory, String pwd) throws Exception{
ZipEntry zipEntry = null;
FileOutputStream outputStream = null;
try{
while ((zipEntry = inputStream.getNextEntry()) != null) {
if (zipEntry.isDirectory()) {
String name = zipEntry.getName();
name = name.substring(0, name.length() - 1);
File file = new File(outputDirectory + File.separator + name);
if(! file.exists()){
file.mkdirs();
}
}else {
File file = new File(outputDirectory + File.separator + zipEntry.getName());
File parentFile = file.getParentFile();
if(! parentFile.exists()){
parentFile.mkdirs();
}
file.createNewFile();
outputStream = new FileOutputStream(file);
if(pwd == null || pwd.trim().equals("")){
int b;
byte[] buffer = new byte[1024];
while ((b = inputStream.read(buffer)) != -1){
outputStream.write(buffer);
}
outputStream.flush();
}else{
PBEKeySpec keySpec = new PBEKeySpec(pwd.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey passwordKey = keyFactory.generateSecret(keySpec);
byte[] salt = new byte[8];
inputStream.read(salt);
int iterations = 100;
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, passwordKey, parameterSpec);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null){
outputStream.write(output);
}
}
byte[] output = cipher.doFinal();
if (output != null){
outputStream.write(output);
}
outputStream.flush();
}
}
}
}
catch(IOException ex){
logger.error(ex);
throw ex;
}catch(Exception ex){
logger.error(ex);
throw ex;
}finally{
if(inputStream != null){
inputStream.close();
}
if(outputStream != null){
outputStream.close();
}

}
}

public static byte[] getByteArrayFromFile(String fileName) throws Exception{
FileInputStream fi = null;
try{
File file = new File(fileName);
long size = file.length();
if (size > Integer.MAX_VALUE) {
throw new Exception("文件太大");
}
fi = new FileInputStream(file);
byte[] buffer = new byte[1024];
byte[] all = new byte[(int) size];
int offset = 0;
int len = 0;
while ((len = fi.read(buffer)) > -1) {
System.array(buffer, 0, all, offset, len);
offset += len;
}
return all;
}catch(Exception ex){
logger.error(ex);
throw ex;
}finally{
if(fi != null){
fi.close();
}
}
}
public static void createFileFromByteArray(byte[] b,String destName) throws Exception{
FileOutputStream os = null;
try{
File destFile = new File(destName);
File parentFile = destFile.getParentFile();
if(! parentFile.exists()){
parentFile.mkdirs();
}
os = new FileOutputStream(destName);
os.write(b);
os.flush();
}catch(Exception e){
logger.error(e);
throw e;
}finally{
if(os != null){
os.close();
}
}

}
public static void main(String[] args) throws Exception{
String fileName = "E:\\sunjinfu\\test\\test.zip";
String outputDir = "E:\\sunjinfu\\test\\csv\\123";
unzip(fileName, outputDir);
}

自己好好研究一下,我只用了其中一部分,你需要就调试调试,也许会有点错误。

C. java怎样使用ZipOutputStream和ZipInputStream压缩和解压缩

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

public class MyZipUtil {

/**
* 设置缓冲值
*/
static final int BUFFER = 8192;

private static final String ALGORITHM = "PBEWithMD5AndDES";

public static void zip(String zipFileName, String inputFile,String pwd) throws Exception {
zip(zipFileName, new File(inputFile), pwd);
}
/**
* 功能描述:压缩指定路径下的所有文件
* @param zipFileName 压缩文件名(带有路径)
* @param inputFile 指定压缩文件夹
* @return
* @throws Exception
*/
public static void zip(String zipFileName, String inputFile) throws Exception {
zip(zipFileName, new File(inputFile), null);
}

/**
* 功能描述:压缩文件对象
* @param zipFileName 压缩文件名(带有路径)
* @param inputFile 文件对象
* @return
* @throws Exception
*/
public static void zip(String zipFileName, File inputFile,String pwd) throws Exception {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
zip(out, inputFile, "",pwd);
out.close();
}

/**
*
* @param out 压缩输出流对象
* @param file
* @param base
* @throws Exception
*/
public static void zip(ZipOutputStream outputStream, File file, String base,String pwd) throws Exception {
if (file.isDirectory()) {
File[] fl = file.listFiles();
outputStream.putNextEntry(new ZipEntry(base + "/"));
base = base.length() == 0 ? "" : base + "/";
for (int i = 0; i < fl.length; i++) {
zip(outputStream, fl[i], base + fl[i].getName(), pwd);
}
}
else {
outputStream.putNextEntry(new ZipEntry(base));
FileInputStream inputStream = new FileInputStream(file);
//普通压缩文件
if(pwd == null || pwd.trim().equals("")){
int b;
while ((b = inputStream.read()) != -1){
outputStream.write(b);
}
inputStream.close();
}
//给压缩文件加密
else{
PBEKeySpec keySpec = new PBEKeySpec(pwd.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey passwordKey = keyFactory.generateSecret(keySpec);
byte[] salt = new byte[8];
Random rnd = new Random();
rnd.nextBytes(salt);
int iterations = 100;
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, passwordKey, parameterSpec);
outputStream.write(salt);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null){
outputStream.write(output);
}
}
byte[] output = cipher.doFinal();
if (output != null){
outputStream.write(output);
}
inputStream.close();
outputStream.flush();
outputStream.close();
}
}
file.delete();
}

public static void unzip(String zipFileName, String outputDirectory)throws Exception {
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(zipFileName));
unzip(inputStream, outputDirectory, null);
}

/**
* 功能描述:将压缩文件解压到指定的文件目录下
* @param zipFileName 压缩文件名称(带路径)
* @param outputDirectory 指定解压目录
* @return
* @throws Exception
*/
public static void unzip(String zipFileName, String outputDirectory, String pwd)throws Exception {
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(zipFileName));
unzip(inputStream, outputDirectory, pwd);
}

public static void unzip(File zipFile, String outputDirectory, String pwd)throws Exception {
ZipInputStream inputStream = new ZipInputStream(new FileInputStream(zipFile));
unzip(inputStream, outputDirectory,pwd);
}

public static void unzip(ZipInputStream inputStream, String outputDirectory, String pwd) throws Exception{
ZipEntry zipEntry = null;
FileOutputStream outputStream = null;
try{
while ((zipEntry = inputStream.getNextEntry()) != null) {
if (zipEntry.isDirectory()) {
String name = zipEntry.getName();
name = name.substring(0, name.length() - 1);
File file = new File(outputDirectory + File.separator + name);
file.mkdir();
}
else {
File file = new File(outputDirectory + File.separator + zipEntry.getName());
file.createNewFile();
outputStream = new FileOutputStream(file);
//普通解压缩文件
if(pwd == null || pwd.trim().equals("")){
int b;
while ((b = inputStream.read()) != -1){
outputStream.write(b);
}
outputStream.close();
}
//解压缩加密文件
else{
PBEKeySpec keySpec = new PBEKeySpec(pwd.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey passwordKey = keyFactory.generateSecret(keySpec);
byte[] salt = new byte[8];
inputStream.read(salt);
int iterations = 100;
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, iterations);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, passwordKey, parameterSpec);
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null){
outputStream.write(output);
}
}
byte[] output = cipher.doFinal();
if (output != null){
outputStream.write(output);
}
outputStream.flush();
outputStream.close();
}
}
}
inputStream.close();
}
catch(IOException ex){
throw new Exception("解压读取文件失败");
}
catch(Exception ex){
throw new Exception("解压文件密码不正确");
}
finally{
inputStream.close();
outputStream.flush();
outputStream.close();
}
}

public static void main(String[] args) {
try {
zip("D:\\SHYJ\\Email\\OUT\\webapps\\test.zip", "D:\\SHYJ\\Email\\OUT\\webapps\\export");
System.out.println("success");
}
catch (Exception e) {
e.printStackTrace(System.out);
}
}
}

D. java如何读取一个加密后的.xls文件

近日来,研究了一下Excel Biff8(xls 97-2007)与OpenXML(ECMA-376)的加密文档的读取(这还是为了我们世界先进Grid而做的 ^__^)。有些成果,写在这里,希望能给要做类似功能的XD们一些参考。
如有不详,请联系:[email protected] / [email protected]
前提:
1. 加密文档:指Wookbook级的加密,就是在Save Excel文档时在General Settings中设置open password之后的文档;
2. 打开:需要用户传入密码。并非破解。但请勿将本文方法添加暴力模块使用 :-) ;
3. 本文涉及较多为,密钥计算,关于解密细节请参考微软相关文档;
使用的加密算法: RC4, SHA1, MD5, AES-128(其中RC4并不包含在所有版本的.NET Framework中,AES算法可以在.NET Framework 3.5中找到)
本文示例依赖 .NET Framework 3.5

A. Biff8 的加密文档读取
1. 通过文档中FILEPASS的record取得,文档的加密信息(关于Biff文档的格式问题,请参阅Biff的微软文档)
其中Biff8可以使用两种方法加密:Biff8标准加密算法和Biff8扩充加密算法。本文主要讨论最常用的Biff标准加密算法
2. 通过FILEPASS的结构,获得如下信息:
salt(加密随机数,16 bytes)
password verifier (密码效验器,16 bytes)
password verifier hash(密码效验器Hash,16 bytes)
3. 通过以上信息,生成解密key。并通过密码效验器,验证密码:
i. 将密码转化成unicode数组,并进行MD5 Hash;
ii. 将hash结果与salt串联,然后将byte数组,反复串联16次(336 bytes) ,然后再进行MD5 Hash;
iii. 将上步hash结果的前五位,串联上4 bytes的block值(在密码验证阶段为0,在以后解密阶段为block的index) ,然后进行MD5 Hash;
iv. 将上步hash结果的前16位,作为key
v. 使用RC4对称加密算法,将password verifier和password verifier hash分别解密,然后对password verifier的解密结果进行MD5 hash,其值应和password verifier hash的解密结果一致,即为密码正确。
vi. 之后进行逐个record的解密。excel biff8加密原则基本为,record的标示不加密,长度不加密,个别record不加密(见文档);另外,在record解密时,还需要通过block的值重新计算解密key,block的大小为1024.
4. 详细请参照示例代码;

B. OpenXML(ECMA-376) 加密文档的读取
1. 通常来说,xlsx文件相当于一个zip文件,可以用zip程序,直接打开。而在加密后,为了安全性考虑,微软使用了 structured storage(一种OLE文档存储方式)存储(可以用7-zip或者OLE document viewer打开,windows也有相应API来操作此类结构)。在上述文档中,有一个叫做“EncryptedPackage”加密的package,就是一个zip包通过AES算法进行加密之后的结果。我们将使用和A一样的方式来检查密码,但生成key的方法不同;OpenXML的加密类型也有多种,我们这里就讨论常用的用AES-128进行加密的流程;
2. 通过文档的“EncryptedInfo”部分,需要过的一下信息(关于此部分的结构,请参考[MS-OFFCRYPTO].pdf)
salt(加密随机数,16 bytes)
password verifier (密码效验器,16 bytes)
password verifier hash(密码效验器Hash,32 bytes)
3. 通过以上信息,生成解密key。并通过密码效验器,验证密码:
i. 首先,定义一个H函数,其有两个输入,内部使用SHA1算法将两个输入串联之后的结果hash返回;
ii. 先将salt与password(password的unicode数组)进行H计算,h = H(salt, password) ;
iii.然后设iterator为0x00000000,将其转为4byte的数组,然后进行H计算,h1 = H(iterator, h);
iv.将上面的iterator递增一,然后再与h1进行H计算,h2 = H(iterator,h1),然后将这个递增和计算过程重复50000次,最后计算过的iterator为49999即可;
v. 现在有计算结果h50000,将h50000再与0x00000000(4 byte数组)进行H计算,Hfinal = H(h50000, 0x00000000);
vi. 生成一个64byte的数组,将每位都初始化成0x36,然后将这个数组与Hfinal异或;(关于这个地方,微软文档中写的有错误,按照原文的方法生成的key不正确,要不是文档的作者回信告诉我要使用这个法子,就算我想破头也想不出来啊 T__T)
vii.将异或结果,进行SHA1 hash,结果的前16byte就是解密的key;
viii.初始化AES算法,key长度为128,模式为ECB模式,Padding为none; 然后将password verifier 和password verifier hash分别解密;
ix. password verifier 解密后的SHA1 hash结果应该与password verifier hash解密后的前20byte相同;
4. 关于"EncryptedPackage" 的解密则更为简单,只许将“EncryptedPackage”读入,去除前8byte的size信息后,进行AES解密,即为未加密的标准openxml文档。

参考:
[MS-OFFCRYPTO].pdf
[MS-XLS].pdf
ECMA-376 standards

Reply by "winnow", 2008-09-10, 1:17
-----------------------------------------------------
总结一下, 关于这两种基于密码的加密方法, 基本上都是基于RFC2898 建议, 思想是这样:
输入是用户的密码:password, 输出是提供给加密函数的密钥:key.
考虑安全, 需要使同样的password生成的key不一样, 这样用相同的password加密后的结果就无法比较. 需要一个随机数salt.
另外, 为了使暴力破解的代价增大, 考虑使用一个循环多次的过程, 需要循环次数:iteration_count.
概念上, 生成方法为: 将password和salt进行某种运算, 配合一个Hash函数, 以某种方式循环iteration_count次, 在最后的结果里取一部分作为key输出.
具体参照RFC2898中的建议方法PBKDF1和PBKDF2.
这样, 用户输入的密码与一个随机数组合, 经过一定代价的运算, 就生成了可以供加密函数使用的密钥. 使用这个密钥和一个加密函数, 就可以进行加密了.

在应用中, 为了快速判断密码是否错误. 生成一个随机数verifier, 用一个Hash函数计算verifier的hash值:verifier_hash, 分别加密verifier和verifier_hash并保存.
解密的时候, 先分别解密出verifier和verifier_hash, 计算verifier的hash值, 与verifier_hash比较, 如果一致, 即说明密码正确.

E. java shiro加盐之后怎么反解密

hash函数是一种单向散列算法,这意味着从明文可以得到散列值,而散列值不可以还原为明文。

验证密码的方法是将用户输入的密码与盐值按照加密时使用的hash算法再hash一次,并与数据库中存储的hash值作比较,若两者一致则认为密码正确。

F. java md5锷犲瘑 index椤甸溃浠g爜


/**
*灏嗘寚瀹歜yte鏁扮粍杞鎹㈡垚16杩涘埗瀛楃︿覆
*@paramb
*@return
*/
(byte[]b){
StringBufferhexString=newStringBuffer();
for(inti=0;i<b.length;i++){
Stringhex=Integer.toHexString(b[i]&0xFF);
if(hex.length()==1){
hex='0'+hex;
}
hexString.append(hex.toUpperCase());
}
returnhexString.toString();
}

/**
*銮峰缑锷犲瘑钖庣殑16杩涘埗褰㈠纺鍙d护
*@parampassword
*@return
*@
*@
*/
(Stringpassword)
,UnsupportedEncodingException{
//澹版槑锷犲瘑钖庣殑鍙d护鏁扮粍鍙橀噺
byte[]pwd=null;
//闅忔満鏁扮敓鎴愬櫒
SecureRandomrandom=newSecureRandom();
//澹版槑鐩愭暟缁勫彉閲
byte[]salt=newbyte[SALT_LENGTH];
//灏嗛殢链烘暟鏀惧叆鐩愬彉閲忎腑
random.nextBytes(salt);

//澹版槑娑堟伅鎽樿佸硅薄
MessageDigestmd=null;
//鍒涘缓娑堟伅鎽樿
md=MessageDigest.getInstance("MD5");
//灏嗙洂鏁版嵁浼犲叆娑堟伅鎽樿佸硅薄
md.update(salt);
//灏嗗彛浠ょ殑鏁版嵁浼犵粰娑堟伅鎽樿佸硅薄
md.update(password.getBytes("UTF-8"));
//銮峰缑娑堟伅鎽樿佺殑瀛楄妭鏁扮粍
byte[]digest=md.digest();

//锲犱负瑕佸湪鍙d护镄勫瓧鑺傛暟缁勪腑瀛樻斁鐩愶纴镓浠ュ姞涓婄洂镄勫瓧鑺傞暱搴
pwd=newbyte[digest.length+SALT_LENGTH];
//灏嗙洂镄勫瓧鑺傛嫹璐濆埌鐢熸垚镄勫姞瀵嗗彛浠ゅ瓧鑺傛暟缁勭殑鍓12涓瀛楄妭锛屼互渚垮湪楠岃瘉鍙d护镞跺彇鍑虹洂
System.array(salt,0,pwd,0,SALT_LENGTH);
//灏嗘秷鎭鎽樿佹嫹璐濆埌锷犲瘑鍙d护瀛楄妭鏁扮粍浠庣13涓瀛楄妭寮濮嬬殑瀛楄妭
System.array(digest,0,pwd,SALT_LENGTH,digest.length);
//灏嗗瓧鑺傛暟缁勬牸寮忓姞瀵嗗悗镄勫彛浠よ浆鍖栦负16杩涘埗瀛楃︿覆镙煎纺镄勫彛浠
returnbyteToHexString(pwd);
}

publicstaticvoidmain(String[]args){//娴嬭瘯鏂规硶
try{
System.out.println(getEncryptedPwd("123456"));
}catch(NoSuchAlgorithmExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(UnsupportedEncodingExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}

鍦╦sp椤甸溃涓鍙浠ヨ皟鐢╣etEncryptedPwd鏂规硶

G. 一个php加密方法,怎么用java实现,高分!

Java OpenSSLPBEInputStream


importjava.io.IOException;
importjava.io.InputStream;
importjava.security.;
importjava.security.InvalidKeyException;
importjava.security.NoSuchAlgorithmException;
importjava.security.spec.InvalidKeySpecException;

importjavax.crypto.BadPaddingException;
importjavax.crypto.Cipher;
importjavax.crypto.IllegalBlockSizeException;
importjavax.crypto.NoSuchPaddingException;

{

privatefinalstaticintREAD_BLOCK_SIZE=64*1024;

privatefinalCiphercipher;
;
privatefinalbyte[]bufferCipher=newbyte[READ_BLOCK_SIZE];

privatebyte[]bufferClear=null;

privateintindex=Integer.MAX_VALUE;
privateintmaxIndex=0;

publicOpenSSLPBEInputStream(finalInputStreamstreamIn,StringalgIn,intiterationCount,char[]password)
throwsIOException{
this.inStream=streamIn;
try{
byte[]salt=readSalt();
cipher=OpenSSLPBECommon.initializeCipher(password,salt,Cipher.DECRYPT_MODE,algIn,iterationCount);
}catch(Exceptione){
thrownewIOException(e);
}
}

@Override
publicintavailable()throwsIOException{
returninStream.available();
}

@Override
publicintread()throwsIOException{

if(index>maxIndex){
index=0;
intread=inStream.read(bufferCipher);
if(read!=-1){
bufferClear=cipher.update(bufferCipher,0,read);
}
if(read==-1||bufferClear==null||bufferClear.length==0){
try{
bufferClear=cipher.doFinal();
}catch(Exceptione){
bufferClear=null;
}
}
if(bufferClear==null||bufferClear.length==0){
return-1;
}
maxIndex=bufferClear.length-1;
}

if(bufferClear==null||bufferClear.length==0){
return-1;
}

returnbufferClear[index++]&0xff;

}

privatebyte[]readSalt()throwsIOException{

byte[]headerBytes=newbyte[OpenSSLPBECommon.OPENSSL_HEADER_STRING.length()];
inStream.read(headerBytes);
StringheaderString=newString(headerBytes,OpenSSLPBECommon.OPENSSL_HEADER_ENCODE);

if(!OpenSSLPBECommon.OPENSSL_HEADER_STRING.equals(headerString)){
thrownewIOException("unexpectedfileheader"+headerString);
}

byte[]salt=newbyte[OpenSSLPBECommon.SALT_SIZE_BYTES];
inStream.read(salt);

returnsalt;
}

}

Java OpenSSLPBEOutputStream

importjava.io.IOException;
importjava.io.OutputStream;
importjava.security.SecureRandom;

importjavax.crypto.Cipher;

{

privatestaticfinalintBUFFER_SIZE=5*1024*1024;

privatefinalCiphercipher;
;
privatefinalbyte[]buffer=newbyte[BUFFER_SIZE];
privateintbufferIndex=0;

publicOpenSSLPBEOutputStream(finalOutputStreamoutputStream,StringalgIn,intiterationCount,
char[]password)throwsIOException{
outStream=outputStream;
try{
/*.*/
byte[]salt=newbyte[OpenSSLPBECommon.SALT_SIZE_BYTES];
newSecureRandom().nextBytes(salt);
cipher=OpenSSLPBECommon.initializeCipher(password,salt,Cipher.ENCRYPT_MODE,algIn,iterationCount);
/*Writeheader*/
writeHeader(salt);
}catch(Exceptione){
thrownewIOException(e);
}
}

@Override
publicvoidwrite(intb)throwsIOException{
buffer[bufferIndex]=(byte)b;
bufferIndex++;
if(bufferIndex==BUFFER_SIZE){
byte[]result=cipher.update(buffer,0,bufferIndex);
outStream.write(result);
bufferIndex=0;
}
}

@Override
publicvoidflush()throwsIOException{
if(bufferIndex>0){
byte[]result;
try{
result=cipher.doFinal(buffer,0,bufferIndex);
outStream.write(result);
}catch(Exceptione){
thrownewIOException(e);
}
bufferIndex=0;
}
}

@Override
publicvoidclose()throwsIOException{
flush();
outStream.close();
}

privatevoidwriteHeader(byte[]salt)throwsIOException{
outStream.write(OpenSSLPBECommon.OPENSSL_HEADER_STRING.getBytes(OpenSSLPBECommon.OPENSSL_HEADER_ENCODE));
outStream.write(salt);
}

}


Main Class 测试以上两个class

importjavax.crypto.Cipher;
importjavax.crypto.NoSuchPaddingException;
importjavax.crypto.SecretKey;
importjavax.crypto.SecretKeyFactory;
importjavax.crypto.spec.PBEKeySpec;
importjavax.crypto.spec.PBEParameterSpec;
importjava.security.;
importjava.security.InvalidKeyException;
importjava.security.NoSuchAlgorithmException;
importjava.security.spec.InvalidKeySpecException;

classOpenSSLPBECommon{

protectedstaticfinalintSALT_SIZE_BYTES=8;
_HEADER_STRING="Salted__";
_HEADER_ENCODE="ASCII";

(char[]password,byte[]salt,intcipherMode,
finalStringalgorithm,intiterationCount),InvalidKeySpecException,
InvalidKeyException,NoSuchPaddingException,{

PBEKeySpeckeySpec=newPBEKeySpec(password);
SecretKeyFactoryfactory=SecretKeyFactory.getInstance(algorithm);
SecretKeykey=factory.generateSecret(keySpec);

Ciphercipher=Cipher.getInstance(algorithm);
cipher.init(cipherMode,key,newPBEParameterSpec(salt,iterationCount));

returncipher;
}
}

来源引用

https://github.com/guardianproject/ChatSecureAndroid/tree/master/src/info/guardianproject/otr

热点内容
大数据缓存 发布:2024-11-25 14:29:07 浏览:435
存储体与MAR 发布:2024-11-25 14:23:08 浏览:282
电脑浏览器怎么取消配置文件 发布:2024-11-25 14:20:39 浏览:163
如何消除服务器数据传输瓶颈 发布:2024-11-25 14:08:48 浏览:288
安卓开发程序如何上传到手机上 发布:2024-11-25 14:08:30 浏览:28
访客qq获取系统源码 发布:2024-11-25 14:08:30 浏览:17
网站如何上传数据库 发布:2024-11-25 14:08:29 浏览:794
怎么操作让安卓手机假装黑屏 发布:2024-11-25 14:07:42 浏览:163
java内部类访问权限 发布:2024-11-25 14:05:59 浏览:342
安卓为什么不分身 发布:2024-11-25 13:54:13 浏览:369