DES decryption in Ruby - ruby

The following is my java code for DES decryption:
public static byte[] decrypt(final byte[] value, final String key) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
final DESKeySpec objDesKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
final SecretKeyFactory objKeyFactory = SecretKeyFactory.getInstance("DES");
final SecretKey objSecretKey = objKeyFactory.generateSecret(objDesKeySpec);
final byte[] rgbIV = key.getBytes();
final IvParameterSpec iv = new IvParameterSpec(rgbIV);
final Cipher objCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
objCipher.init(2, objSecretKey, iv);
return objCipher.doFinal(value);
}
And I try to convert it to Ruby code as the following:
def decryption(key, decodeString)
ALG = 'des'
cipher = OpenSSL::Cipher::Cipher.new(ALG)
cipher.decrypt #choose descryption mode.
cipher.key = key
plain = cipher.update(decodeString )
plain << cipher.final
end
After executing the java and ruby code, I got the same size of bytes, but the contents of bytes are different. Where did I go wrong?

Thanks for your question!
To do this, use the OpenSSL::Cipher library. Here is a link with some sample code for AES: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html#class-OpenSSL::Cipher-label-Encrypting+and+decrypting+some+data
To use DES, run this command to see if your Ruby installation supports DES.
puts OpenSSL::Cipher.ciphers

According to this article : http://43n141e.blogspot.tw/2008/08/des-encryption-java-to-openssl-to-ruby.html , I try the following two steps :
1. Calculate iv value in Java:
String key = "123456"
final byte[] rgbIV = key.getBytes();
final IvParameterSpec iv = new IvParameterSpec(rgbIV);
byte[] ivBytes = iv.getIV();
StringBuffer sbuf = new StringBuffer();
for (byte b : ivBytes) {
sbuf.append(String.format("%02x", (b & 0xFF)));
}
System.out.println("iv: " + sbuf);
2. Decrypt in Ruby :
def decode(encryptedString, key, iv)
decrypt = OpenSSL::Cipher::Cipher.new('des-cbc')
decrypt.decrypt
decrypt.key = key
decrypt.iv = iv.scan(/../).map{|b|b.hex}.pack('c*')
decrypt.update(encryptedString) + decrypt.final
end
and it works !

Related

How to implement DES encrypting with ('DES/CBC/PKCS5Padding' mode) in Ruby?

I'v received on some DES encrypted stuff from a 3rd part company. I can't decrypt it in ruby. But it works in my java code.
Here is java code:
public class Main {
public static void main(String[] args) {
try {
System.out.println(encrypt("12345678", "abc", "12345678"));
//System.out.println(encrypt("12345678", "ABC", "12345678"));
System.out.println(decrypt("12345678", "9YR6ZPdZufM=", "12345678"));
//System.out.println(decrypt("12345678", "6rtTnrF34mPkJ5SO3RiaaQ==", "12345678"));
} catch (Exception e) {
e.printStackTrace();
}
}
public static String encrypt(String key, String str, String ivString) throws Exception {
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
Key secretKey = keyFactory.generateSecret(desKeySpec);
IvParameterSpec iv = new IvParameterSpec(ivString.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] bytes = cipher.doFinal(str.getBytes());
dumpHex(bytes);
return Base64.encode(bytes);
}
public static void dumpHex(byte[] bytes) {
for (byte b : bytes) {
System.out.println(String.format("%02x",b&0xff));
}
System.out.println(bytesToHex(bytes));
}
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static String decrypt(String key, String str, String ivString) throws Exception {
byte[] data = Base64.decode(str);
dumpHex(data);
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
Key secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(ivString.getBytes());
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] decryptedBytes = cipher.doFinal(data);
return new String(decryptedBytes, "gb2312");
}
}
I couldn't found the same DES mode ('DES/CBC/PKCS5Padding') in ruby. I got the different result when I try to encrypt the same string.
Here is my ruby source code:
class Des
require 'openssl'
require 'base64'
ALG = 'DES-EDE3-CBC'
KEY = "12345678"
DES_KEY = "12345678"
def encode(str)
des = OpenSSL::Cipher::Cipher.new(ALG)
des.pkcs5_keyivgen(KEY, DES_KEY)
des.encrypt
cipher = des.update(str) + des.final
pp cipher.length
pp cipher.unpack('H*')[0]
return Base64.encode64(cipher)
end
def decode(str)
str = Base64.decode64(str)
pp str.unpack('H*')[0]
des = OpenSSL::Cipher::Cipher.new(ALG)
des.pkcs5_keyivgen(KEY, DES_KEY)
des.decrypt
des.update(str) + des.final
end
def KEY()
pp KEY.length
KEY
end
def DES_KEY()
pp DES_KEY.length
DES_KEY
end
end
I encrypt 'abc' with java, get "9YR6ZPdZufM=". But get "5SHCjTOrygg=" in ruby version.It confused me a lot.
I change some config in ruby code, and it works. But I didn't know why...
def DES
ALG = 'DES-EDE-CBC'
KEY = "1234567812345678"
DES_KEY = "12345678"

Create a Case Sensitive Login Form in VB 10

I want to Create a Login Form that the fields in password are case sensitive example if my passwords is "PassWord" it will only accepts the keyword "PassWord" and not accepts "password" Or "PASSWORD" keyword etc. I want it a character sensitive thanks Please Help me Im a new Programmer using DATABASE MS ACCESS Thanks Here is my code
Private Sub btnLog_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLog.Click
Try
Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\NIASecurity.accdb")
Dim cmd As OleDbCommand = New OleDbCommand("SELECT [Username] FROM [Security] WHERE [Username] = #User and Password =#Pass ", con)
cmd.Parameters.AddWithValue("#User", txtUser.Text)
cmd.Parameters.AddWithValue("#Pass", txtPass.Text)
con.Open()
Dim sdr As OleDbDataReader = cmd.ExecuteReader()
If sdr.Read Then
If txtPass.Text = sdr(0) Then
MessageBox.Show("Welcome")
Dim win As New frmAdd
win.MdiParent = frmMDI
win.Show()
Me.Close()
Else
MsgBox("Invalid name or password!")
End If
End If
Catch ex As Exception
MessageBox.Show("Invalid name or password!")
End Try
End Sub
I can say you for save passwords in db, you must save password Data with Hashing Algorithm such as MD5 or SHA1
When user type password for login you hash string that typed for password and compare this string with password that save in db
public static void HashPassword(string Password, out string Salt, out string Hash)
{
System.Security.Cryptography.SHA1Managed sha = new System.Security.Cryptography.SHA1Managed();
Random rnd = new Random();
byte[] s = new byte[20];
rnd.NextBytes(s);
Salt = Convert.ToBase64String(s);
System.Text.UTF8Encoding u = new UTF8Encoding();
byte[] pass = u.GetBytes(Password);
byte[] all = new byte[pass.Length + s.Length];
Array.Copy(pass, all, pass.Length);
Array.Copy(s, 0, all, pass.Length, s.Length);
Byte[] H = sha.ComputeHash(all);
Hash = Convert.ToBase64String(H);
}
public bool IsPasswordCorrect(string Password, string Salt, string Hash)
{
System.Security.Cryptography.SHA1Managed sha = new System.Security.Cryptography.SHA1Managed();
byte[] s = Convert.FromBase64String(Salt);
System.Text.UTF8Encoding u = new UTF8Encoding();
byte[] pass = u.GetBytes(Password);
byte[] all = new byte[pass.Length + s.Length];
Array.Copy(pass, all, pass.Length);
Array.Copy(s, 0, all, pass.Length, s.Length);
Byte[] H = sha.ComputeHash(all);
return (Hash == Convert.ToBase64String(H));
}
now you must use HashPassword method to give hash an salt and save hash and salt to db for every user.
When want to check password use IsPasswordcorrect Method

Bad Data cryptographicexception in xml using Linq in c#

My XML file:
<?xml version="1.0" encoding="utf-8"?>
<dskh>
<khachhang maso="kh01">
<ten_kh>thehung</ten_kh>
<tuoi_kh>15</tuoi_kh>
<dchi_kh>hochiminh</dchi_kh>
</khachhang>
<khachhang maso="kh02">
<ten_kh>hung</ten_kh>
<tuoi_kh>15</tuoi_kh>
<dchi_kh>hcm</dchi_kh>
</khachhang>
</dskh>
My Encrypt and Decrypt code:
class Program
{
// Call this function to remove the key from memory after use for security.
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint = "RtlZeroMemory")]
public static extern bool ZeroMemory(ref string Destination, int Length);
// Function to Generate a 64 bits Key.
static string GenerateKey()
{
// Create an instance of Symetric Algorithm. Key and IV is generated automatically.
DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
// Use the Automatically generated key for Encryption.
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
}
static void EncryptFile(string sInputFilename,
string sOutputFilename,
string sKey) {
FileStream fsInput = new FileStream(sInputFilename,FileMode.Open,FileAccess.Read);
FileStream fsEncrypted = new FileStream(sOutputFilename,FileMode.Create,FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = Encoding.UTF8.GetBytes(sKey);
DES.IV = Encoding.UTF8.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
CryptoStream cryptostream = new CryptoStream(fsEncrypted,desencrypt,CryptoStreamMode.Write);
byte[] bytearrayinput = new byte[fsInput.Length - 1];
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
}
static void DecryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
//A 64 bit key and IV is required for this provider.
//Set secret key For DES algorithm.
DES.Key = Encoding.UTF8.GetBytes(sKey);
//Set initialization vector.
DES.IV = Encoding.UTF8.GetBytes(sKey);
//Create a file stream to read the encrypted file back.
FileStream fsread = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
//Create a DES decryptor from the DES instance.
ICryptoTransform desdecrypt = DES.CreateDecryptor();
//Create crypto stream set to read and do a
//DES decryption transform on incoming bytes.
CryptoStream cryptostreamDecr = new CryptoStream(fsread,
desdecrypt,
CryptoStreamMode.Read);
//Print the contents of the decrypted file.
StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
}
static void Main(string[] args)
{
// Must be 64 bits, 8 bytes.
// Distribute this key to the user who will decrypt this file.
string sSecretKey;
// Get the key for the file to encrypt.
sSecretKey = GenerateKey();
// For additional security pin the key.
GCHandle gch = GCHandle.Alloc(sSecretKey, GCHandleType.Pinned);
// Encrypt the file.
EncryptFile(#"C:\xml_kh.xml",
#"C:\xml_encry.xml",
sSecretKey);
//Decrypt the file.
DecryptFile(#"C:\xml_encry.xml",
#"C:\xml_decry.xml",
sSecretKey);
}
}
When i excute Decrypt code, i get Cryptographicexception: Bad Data here:
//Print the contents of the decrypted file.
StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
Please help me!!!
Add two lines at the end of EncryptFile function:
cryptostream.Flush();
cryptostream.Close();
EDIT
I missed there is one more error:
byte[] bytearrayinput = new byte[fsInput.Length - 1];
s/b
byte[] bytearrayinput = new byte[fsInput.Length];

Find public key from certificate as a xml string

i need to find the public key from certificate as xml string. I can take the public key only as a string with this method:
public string CelesiPublik()
{
X509Certificate cer;
cer = X509Certificate.CreateFromCertFile("C://certificate//EdonBajrami.crt");
string Celesi = cer.GetPublicKeyString();
return Celesi;
}
and then i take this value to the another method. Celesi value now has take celesiPublik
celesiPublik = e.Result;
string NrTelefonit = "044-419-109";
string salt = "VotimiElektronikKosove";
AesManaged aes = new AesManaged();
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(celesiPublik,Encoding.UTF8.GetBytes(salt));
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(celesiPublik);
rsa.Encrypt(aes.Key, false);
but it shows me error. How can i resolve this problem?
GregS i cannot use in Windows Phone 7 X509Certificate2. I take my public key with the method:
`X509Certificate cer = new X509Certificate("C://certificate//EdonBajrami.crt");
string publicKey = cer.GetPublicKeyString();`
i can take the public key. Then in another method i take value of the publicKey to another string variable Key:
`string Key = publicKey;
//-----First------
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
//----------
RSAParameters RSAKeyInfo = new RSAParameters();
byte[] celesibyte = System.Text.Encoding.UTF8.GetBytes(celesiPublik);
byte[] Exponent = { 1, 0, 1 };
RSAKeyInfo.Modulus = celesibyte;
RSAKeyInfo.Exponent = Exponent;
rsa.ImportParameters(RSAKeyInfo);
//-----------
/* rsa.FromXmlString(celesi2Publik); */
string edon = "Edon";
byte[] edon1 = Encoding.UTF8.GetBytes(edon);
byte[] edon2 = rsa.Encrypt(edon1, false);'
but it sends me data that is 506 byte, i dont understand why, what is a problem ?
As far as I can tell the X509Certificate class is nearly useless. Perhaps that is why there is a class X509Certificate2? Use the X509Certificate2 class. You can create an RSACryptoServiceProvider directly from the public key like the following:
X509Certificate2 cert = new X509Certificate2(X509Certificate.CreateFromCertFile("C://certificate//EdonBajrami.crt"));
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) cert.PublicKey.Key;

SHA1 with salt on windows phone 7

I have some some time now reshearchd how to encode a password to SHA1 with a salt.
The is the code i used on my web application part, but it will not work on a phone environment.
public class Password
{
private string _password;
private int _salt;
public Password(string strPassword, int nSalt)
{
_password = strPassword;
_salt = nSalt;
}
public string ComputeSaltedHash()
{
// Create Byte array of password string
ASCIIEncoding encoder = new ASCIIEncoding();
Byte[] _secretBytes = encoder.GetBytes(_password);
// Create a new salt
Byte[] _saltBytes = new Byte[4];
_saltBytes[0] = (byte)(_salt >> 24);
_saltBytes[1] = (byte)(_salt >> 16);
_saltBytes[2] = (byte)(_salt >> 8);
_saltBytes[3] = (byte)(_salt);
// append the two arrays
Byte[] toHash = new Byte[_secretBytes.Length + _saltBytes.Length];
Array.Copy(_secretBytes, 0, toHash, 0, _secretBytes.Length);
Array.Copy(_saltBytes, 0, toHash, _secretBytes.Length, _saltBytes.Length);
SHA1 sha1 = SHA1.Create();
Byte[] computedHash = sha1.ComputeHash(toHash);
return encoder.GetString(computedHash);
}
public static int CreateRandomSalt()
{
Byte[] _saltBytes = new Byte[4];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(_saltBytes);
return ((((int)_saltBytes[0]) << 24) + (((int)_saltBytes[1]) << 16) +
(((int)_saltBytes[2]) << 8) + ((int)_saltBytes[3]));
}
public static string CreateRandomPassword(int PasswordLength)
{
String _allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ23456789!\"#ยค%&/()=?$+-_.,;'*";
Byte[] randomBytes = new Byte[PasswordLength];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
char[] chars = new char[PasswordLength];
int allowedCharCount = _allowedChars.Length;
for (int i = 0; i < PasswordLength; i++)
{
chars[i] = _allowedChars[(int)randomBytes[i] % allowedCharCount];
}
return new string(chars);
}
}
Silverlight and Windows Phone 7 do not have an ASCIIEncoding. I suggest you use the UTF8Encoding instead. If you are certain that your passwords are always within the ASCII range then this encoding will work the same as the ASCIIEncoding would of had it been present.
If on the other hand you cannot guarantee that passwords are always within the ASCII range then you would need to make sure both ends hash using the UTF8Encoding to ensure generated hashs are the same.

Resources