當前位置:首頁 » 密碼管理 » 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-09-08 11:46:23 瀏覽:189
聯想存儲機櫃 發布:2024-09-08 11:37:38 瀏覽:680
安卓電腦和蘋果系統哪個好 發布:2024-09-08 11:35:59 瀏覽:861
改進bp演算法 發布:2024-09-08 11:22:23 瀏覽:977
酷狗怎麼清除緩存 發布:2024-09-08 11:17:29 瀏覽:155
開發板主板交叉編譯 發布:2024-09-08 11:12:59 瀏覽:168
手機學c語言軟體 發布:2024-09-08 11:12:03 瀏覽:282
java培訓課程有那些 發布:2024-09-08 11:11:30 瀏覽:654
舊筆記本如何裝安卓系統 發布:2024-09-08 11:10:20 瀏覽:953
安卓怎麼關閉藍牙自動連接 發布:2024-09-08 10:58:12 瀏覽:11