java和.net中的加密结果不一样 [英] encryption result in java and .net are not same

查看:151
本文介绍了java和.net中的加密结果不一样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public string Encrypt(string plainText)
{
string PassPhrase =#$ ^& *!@!$;
string SaltValue =R @ j @} {BAe;
int PasswordIterations = Convert.ToInt32(textBox5.Text); //修改匹配java加密迭代
string InitVector =@ 1B2c3D4e5F6g7H8;
int KeySize = 256; //修改匹配java加密密钥大小

byte [] initVectorBytes = Encoding.ASCII.GetBytes(InitVector);
byte [] saltValueBytes = Encoding.ASCII.GetBytes(SaltValue);

byte [] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

PasswordDeriveBytes password = new PasswordDeriveBytes(
PassPhrase,
saltValueBytes,
MD5,
PasswordIterations);

byte [] keyBytes = password.GetBytes(KeySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;

ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
keyBytes,
initVectorBytes);
MemoryStream memoryStream = new MemoryStream();

CryptoStream cryptoStream = new CryptoStream(memoryStream,
encryptor,
CryptoStreamMode.Write);

cryptoStream.Write(plainTextBytes,0,plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte [] cipherTextBytes = memoryStream.ToArray();

memoryStream.Close();
cryptoStream.Close();

string cipherText = Convert.ToBase64String(cipherTextBytes);

return cipherText;
}

我已经被任命将此方法转换为java,但在java中我不得到与.Net版本相同的结果



我的java代码是

  package com.andc.billing.pdc.security; 

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.management.openmbean.InvalidKeyException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PasswordCrypto {

private static final String password =#$ ^& *!@!$;
private static String initializationVector =@ 1B2c3D4e5F6g7H8;
private static String salt =R @ j @} {BAe;
private static int pswdIterations = 2;
private static int keySize = 128;
private static final Log log = LogFactory.getLog(PasswordCrypto.class);

public static String encrypt(String plainText)throws
NoSuchAlgorithmException,
InvalidKeySpecException,
NoSuchPaddingException,
InvalidParameterSpecException,
IllegalBlockSizeException,
BadPaddingException,
UnsupportedEncodingException,
InvalidKeyException,
InvalidAlgorithmParameterException,java.security.InvalidKeyException,NoSuchProviderException
{
byte [] saltBytes = salt.getBytes(ASCII) ; // UTF-8);
byte [] ivBytes = initializationVector.getBytes(ASCII); //UTF-8);

//导出密钥,给定密码和盐。
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF2WithHmacSHA1); // PBEWithMD5AndDES);
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);

SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded() AES);


密码密码= Cipher.getInstance(AES / CBC / PKCS5Padding); //Cipher.getInstance(\"AES/CBC/PKCSPadding
cipher .init(Cipher.ENCRYPT_MODE,secret,new IvParameterSpec(ivBytes));

byte [] encryptedTextBytes = cipher.doFinal(plainText.getBytes(ASCII)); // UTF-8) );
String str = new org.apache.commons.codec.binary.Base64()。encodeAsString(encryptedTextBytes);
log.info(str);
return str;
}
}

.net 加密1的结果是:

  7mPh3 / E / olBGbFpoA18oqw == 

java

  7RPk77AIKAhOttNLW4e5yQ == 

你能帮助我吗解决这个问题?

解决方案

我注意到的第一件事是你使用的算法是不同的,在.Net中扩展PBKDF1,而在java中,它是 PBKDF2 ,PBKDF2替换了PBKDF1。



在.net中,您使用的是 PasswordDeriveBytes类,它使用PBKDF1算法的扩展从密码中导出密钥。



I也注意到这个密码是迭代的在Java中,ation被硬编码为2,来自.Net中的文本框...确保它们是一样的。



更正并让我们知道结果。



更新:对于.net中的PBKDF2,使用Rfc2898DeriveBytes类。



对于一些非常好的相关信息阅读本页



编辑: 此链接应该有帮助和如果您可以使用 Chilkat图书馆



1和2之间是一个复杂的区别,1只应该做到20个字节,MS已经建立了一个扩展,允许更多的和以下的co de应该更准确地重新排列.net输出。 取自此处

  import org.bouncycastle.crypto.CipherParameters; 
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;


public class PKCS5Test
{
/ **
* @param args
* /
public static void main String [] args)throws Exception
{
byte [] password = {0,1,2,3,4,5,6,7,8,9,10,11,12,13, 14,15};
byte [] salt = PKCS5S1ParametersGenerator.PKCS5PasswordToBytes(MyTesting.toCharArray());

PKCS5S1ParametersGenerator generator = new PasswordDeriveBytes(new SHA1Digest());
generator.init(password,salt,100);

byte [] key =((KeyParameter)generator.generateDerivedParameters(512))。getKey();
System.out.println(64+ new String(Hex.encode(key))。toUpperCase());
}

static class PasswordDeriveBytes extends PKCS5S1ParametersGenerator
{
private final Digest d;

private byte [] output = null;

public PasswordDeriveBytes(Digest d)
{
super(d);

this.d = d;
}

public CipherParameters generateDerivedParameters(int keySize)
{
keySize = keySize / 8;

byte [] result = new byte [keySize];
int done = 0;
int count = 0;
byte [] b = null;

while(done< result.length)
{
if(b == null)
{
b = generateInitialKey();
}
else if(++ count< 1000)
{
b = generateExtendedKey(++ count);
}
else
{
抛出新的RuntimeException(超出限制);
}

int use = Math.min(b.length,result.length - done);
System.arraycopy(b,0,result,done,use);
done + = use;
}

返回新的KeyParameter(result);
}

private byte [] generateOutput()
{
byte [] digestBytes = new byte [d.getDigestSize()];

d.update(password,0,password.length);
d.update(salt,0,salt.length);
d.doFinal(digestBytes,0); (int i = 1; i<(iterationCount - 1); i ++)
{
d.update(digestBytes,0,digestBytes.length);


d.doFinal(digestBytes,0);
}

返回digestBytes;
}

private byte [] generateInitialKey()
{
output = generateOutput();
d.update(output,0,output.length);

byte [] digestBytes = new byte [d.getDigestSize()];
d.doFinal(digestBytes,0);
return digestBytes;
}

private byte [] generateExtendedKey(int count)
{
byte [] prefix = Integer.toString(count).getBytes();
d.update(prefix,0,prefix.length);
d.update(output,0,output.length);

byte [] digestBytes = new byte [d.getDigestSize()];
d.doFinal(digestBytes,0);

//System.err.println(X:+ new String(Hex.encode(digestBytes))。toUpperCase());
return digestBytes;
}
}
}


I have a method in my .net project to encrypt a password

public string Encrypt(string plainText)
{
    string PassPhrase = "#$^&*!@!$";
    string SaltValue = "R@j@}{BAe";
    int PasswordIterations = Convert.ToInt32(textBox5.Text); //amend to match java encryption iteration
    string InitVector = "@1B2c3D4e5F6g7H8";
    int KeySize = 256; //amend to match java encryption key size

    byte[] initVectorBytes = Encoding.ASCII.GetBytes(InitVector);
    byte[] saltValueBytes = Encoding.ASCII.GetBytes(SaltValue);

    byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

    PasswordDeriveBytes password= new PasswordDeriveBytes(
        PassPhrase,
        saltValueBytes,
        "MD5",
        PasswordIterations);

    byte[] keyBytes = password.GetBytes(KeySize / 8);
    RijndaelManaged symmetricKey = new RijndaelManaged();
    symmetricKey.Mode = CipherMode.CBC;

    ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
                                                     keyBytes,
                                                     initVectorBytes);
    MemoryStream memoryStream = new MemoryStream();

    CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                 encryptor,
                                                 CryptoStreamMode.Write);

    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
    cryptoStream.FlushFinalBlock();
    byte[] cipherTextBytes = memoryStream.ToArray();

    memoryStream.Close();
    cryptoStream.Close();

    string cipherText = Convert.ToBase64String(cipherTextBytes);

    return cipherText;
}

I have been tasked to convert this method to java but in java I don't get the same result as the .Net version

My java code is

package com.andc.billing.pdc.security;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.management.openmbean.InvalidKeyException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PasswordCrypto {

    private static final String password = "#$^&*!@!$";
    private static String initializationVector = "@1B2c3D4e5F6g7H8";
    private static String salt = "R@j@}{BAe";
    private static int pswdIterations = 2;
    private static int keySize = 128;
    private static final Log log = LogFactory.getLog(PasswordCrypto.class);

    public static String encrypt(String plainText) throws 
        NoSuchAlgorithmException, 
        InvalidKeySpecException, 
        NoSuchPaddingException, 
        InvalidParameterSpecException, 
        IllegalBlockSizeException, 
        BadPaddingException, 
        UnsupportedEncodingException, 
        InvalidKeyException, 
        InvalidAlgorithmParameterException, java.security.InvalidKeyException, NoSuchProviderException 
    {   
        byte[] saltBytes = salt.getBytes("ASCII");//"UTF-8");
        byte[] ivBytes = initializationVector.getBytes("ASCII");//"UTF-8");

        // Derive the key, given password and salt.
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");//PBEWithMD5AndDES");
        PBEKeySpec spec = new PBEKeySpec(
                password.toCharArray(), 
                saltBytes, 
                pswdIterations, 
                keySize
        );

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");


        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Cipher.getInstance("AES/CBC/PKCSPadding"
        cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(ivBytes));

        byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("ASCII"));//UTF-8"));
        String str=new org.apache.commons.codec.binary.Base64().encodeAsString(encryptedTextBytes);
        log.info(str);
        return str;
    }
}

.net result of encryption of "1" is :

7mPh3/E/olBGbFpoA18oqw==

while java is

7RPk77AIKAhOttNLW4e5yQ==

Would you please help me solve this problem ?

解决方案

First thing i've noticed is that the algorithms you are using are different, in .Net it's an extension of PBKDF1 and in java it's PBKDF2, PBKDF2 replaced PBKDF1.

In .net you are using the PasswordDeriveBytes class which "derives a key from a password using an extension of the PBKDF1 algorithm."

I also notice that the password iterations is hard-coded to 2 in Java and comes from a text box in .Net... ensure they are the same.

Correct that and let us know the outcome.

Update: For PBKDF2 in .net use the Rfc2898DeriveBytes class.

For some very good relevant information have a read of this page

EDIT: This link should be helpful and if you can use the Chilkat library

It's a complicated difference between 1 and 2, 1 is only supposed to do upto 20 bytes, MS has built an extension which allows more than that and the following code should reporduce the .net output more accurately. Taken from here.

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;


public class PKCS5Test
{
    /**
     * @param args
     */
    public static void main(String[] args) throws Exception
    {
        byte[] password = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
        byte[] salt = PKCS5S1ParametersGenerator.PKCS5PasswordToBytes("MyTesting".toCharArray());

        PKCS5S1ParametersGenerator generator = new PasswordDeriveBytes(new SHA1Digest());
        generator.init(password, salt, 100);

        byte[] key = ((KeyParameter)generator.generateDerivedParameters(512)).getKey();
        System.out.println( "64 " + new String(Hex.encode(key)).toUpperCase() );
    }

    static class PasswordDeriveBytes extends PKCS5S1ParametersGenerator
    {
        private final Digest d;

        private byte[] output = null;

        public PasswordDeriveBytes(Digest d)
        {
            super(d);

            this.d = d;
        }

        public CipherParameters generateDerivedParameters(int keySize)
        {
            keySize = keySize / 8;

            byte[] result = new byte[keySize];
            int done = 0;
            int count = 0;
            byte[] b = null;

            while (done < result.length)
            {
                if (b == null)
                {
                    b = generateInitialKey();
                }
                else if (++count < 1000)
                {
                    b = generateExtendedKey(++count);
                }
                else
                {
                    throw new RuntimeException("Exceeded limit");
                }

                int use = Math.min(b.length, result.length - done);
                System.arraycopy(b, 0, result, done, use);
                done += use;
            }

            return new KeyParameter(result);
        }

        private byte[] generateOutput()
        {
            byte[] digestBytes = new byte[d.getDigestSize()];

            d.update(password, 0, password.length);
            d.update(salt, 0, salt.length);
            d.doFinal(digestBytes, 0);

            for (int i = 1; i < (iterationCount - 1); i++)
            {
                d.update(digestBytes, 0, digestBytes.length);
                d.doFinal(digestBytes, 0);
            }

            return digestBytes;
        }

        private byte[] generateInitialKey()
        {
            output = generateOutput();
            d.update(output, 0, output.length);

            byte[] digestBytes = new byte[d.getDigestSize()];
            d.doFinal(digestBytes, 0);
            return digestBytes;
        }

        private byte[] generateExtendedKey(int count)
        {
            byte[] prefix = Integer.toString(count).getBytes();
            d.update(prefix, 0, prefix.length);
            d.update(output, 0, output.length);

            byte[] digestBytes = new byte[d.getDigestSize()];
            d.doFinal(digestBytes, 0);

            //System.err.println( "X: " + new String(Hex.encode(digestBytes)).toUpperCase() );
            return digestBytes;
        }
    }
} 

这篇关于java和.net中的加密结果不一样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆