Dobrý den,
potřeboval bych přepsat šifrovací algoritmus, který je napsán v .NETu (tedy úplně prapůvodně je v PowerBuilderu) do javy.
V C# to vypadá takto:
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptAcquireContext(out IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptCreateHash(IntPtr hProv, ALG_ID Algid, IntPtr hKey, uint dwFlags, out IntPtr phHash);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, int dwDataLen, uint dwFlags);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDeriveKey(IntPtr hProv, ALG_ID Algid, IntPtr hBaseData, uint dwFlags, out IntPtr phKey);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptEncrypt(IntPtr hKey, IntPtr hHash, int Final, uint dwFlags, byte[] pbData, out uint pdwDataLen, uint dwBufLen);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDestroyHash(IntPtr hHash);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, [MarshalAs(UnmanagedType.Bool)] bool Final, uint dwFlags, byte[] pbData, ref int pdwDataLen);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDestroyKey(IntPtr hKey);
[DllImport("advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
public const uint PROV_RSA_FULL = 0x00000001;//1;
public const uint CRYPT_VERIFYCONTEXT = 0xF0000000; //; 4026531840;
public enum ALG_ID
{
CALG_MD5 = 0x00008003,//32771,
CALG_RC2 = 26114,
CALG_RC4 = 26625
}
const string MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
public static string GetHashPassword(string str, string Password)
{
IntPtr hCryptProv;
IntPtr hKey;
IntPtr hHash;
System.Text.ASCIIEncoding _encoding = new System.Text.ASCIIEncoding();
byte[] BPassword = _encoding.GetBytes(Password);
CryptAcquireContext(out hCryptProv, null, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT );
if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_MD5, IntPtr.Zero, 0, out hHash))
return "";
if (!CryptHashData(hHash, BPassword, BPassword.Length, 0))
return "";
if (!CryptDeriveKey(hCryptProv, ALG_ID.CALG_RC4, hHash, 0, out hKey))
return "";
uint DataLen = Convert.ToUInt32(str.Length);
uint BufLen = Convert.ToUInt32(str.Length);
CryptEncrypt(hKey, IntPtr.Zero, 1, 0, null, out BufLen, 0);
int blen = Convert.ToInt32(BufLen);
//if the line is more than buffer it is cut off
if (str.Length >= blen)
{
str = str.Substring(0, Convert.ToInt32(BufLen));
}
byte[] Bstr = _encoding.GetBytes(str);
//if the line is less than buffer it is finished by its zero
if (Bstr.Length <= blen)
{
byte[] NewBstr = new byte[blen];
Bstr.CopyTo(NewBstr, 0);
Bstr = NewBstr;
}
CryptEncrypt(hKey, IntPtr.Zero, 1, 0, Bstr, out DataLen, BufLen);
//return BitConverter.ToString(Bstr);
//string st = Convert.ToBase64String(Bstr);
return ASCIIEncoding.ASCII.GetString(Bstr);
}
a Do javy jsem to přepsal tímto způsobem:
public static void encrypt2(String password, String plainText, String charset)
throws Exception
{
byte[] passwordData = password.getBytes(charset);
byte[] textData = plainText.getBytes(charset);
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
byte[] md5HashPass = md.digest(passwordData);
SecretKeySpec rc2KeySpec = new SecretKeySpec(md5HashPass, "RC4");
Cipher rc4 = Cipher.getInstance("RC4");
rc4.init(Cipher.ENCRYPT_MODE, rc2KeySpec);
byte[] cipher = rc4.doFinal(textData);
String out = new String(cipher, charset);
// if (out.toUpperCase().startsWith("L"))
{
System.out.println("*encrypt2 **********************");
System.out.println(out);
}
}
Problém je v tom, že .NETí funkce vrací něco jiného než java. Pokud jsem si změnil providera ve funkci
CryptAcquireContext na "Microsoft Strong Cryptographic Provider", pak se vrací úplně stejný řetězec jako v javě. Ale potřeboval bych tam "Microsoft Base Cryptographic Provider v1.0",
tak jak je v původním kódu.
V šifrofání nejsem vůbec zběhlý. Prosím tedy o pomoc, co změnit ve funkci encrypt2, aby to vracelo stejná data jako GetHashPassword.
Je třeba instalovat na cílový stroj nějakého providera? Cílově by tato funkce měla jet na windows i androidu.
Děkuji předem za jakékoliv podněty