Reputation: 125
I have my c# server and my java client, their communication is encrypted but when the client sends an encrypted query, the server cant decrypt it, well it can but its totally unreadable, its like converting a byte array to a string, totally unreadable, this is the encryption on the clients side:
public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING);
final byte[] keyData = Arrays.copyOf(passwordBytes, KEY_SIZE
/ Byte.SIZE);
final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize());
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyData, "AES"),
new IvParameterSpec(ivBytes));
encryptedBytes = cipher.doFinal(bytesToBeEncrypted);
return encryptedBytes;
}
And the decryption on the server side:
internal string DecryptText(string inputString, Key k)
{
try
{
inputString = inputString.Replace("\0", "");
byte[] decryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
byte[] bytesToBeDecrypted = Convert.FromBase64String(inputString);
byte[] passwordBytes = Encoding.UTF8.GetBytes("azaz");
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Padding = PaddingMode.None;
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return Encoding.UTF8.GetString(decryptedBytes);
}
catch (Exception ex)
{
throw new SystemException(ex.Message);
}
}
Thanks in advance
EDIT On the java client, this function call the AES_Encrypt function:
public String EncryptText(String input) throws NoSuchAlgorithmException
{
byte[] bytesToBeEncrypted = input.getBytes();
byte[] passwordBytes = Config.ServerKey.getBytes();
MessageDigest md = MessageDigest.getInstance("SHA-256");
passwordBytes = md.digest(passwordBytes);
byte[] bytesEncrypted = null;
try {
bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex);
}
return Base64.getEncoder().encodeToString(bytesEncrypted);
}
EDIT Implemented basic SslStream and verification server side
private void Do()
{
int requestCount = 0;
string serverResponse = null;
string rCount = null;
string dataFromClient = null;
Byte[] sendBytes = null;
requestCount = 0;
Responder.Responder R = new Responder.Responder();
while ((true))
{
try
{
byte[] buffer = new byte[4];
requestCount = requestCount + 1;
bool leaveInnerStreamOpen = true;
RemoteCertificateValidationCallback validationCallback =
new RemoteCertificateValidationCallback(ClientValidationCallback);
LocalCertificateSelectionCallback selectionCallback =
new LocalCertificateSelectionCallback(ServerCertificateSelectionCallback);
EncryptionPolicy encryptionPolicy = EncryptionPolicy.AllowNoEncryption;
_sslStream = new SslStream(clientSocket.GetStream(),
leaveInnerStreamOpen, validationCallback, selectionCallback, encryptionPolicy);
X509Certificate2 certificate = ServerCertificate.Servercertificate(); //method that has access to the embedded certificate
bool requireClientCertificate = true;
SslProtocols enabledSslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12;
bool checkCertificateRevocation = true;
_sslStream.AuthenticateAsServer
(certificate, requireClientCertificate, enabledSslProtocols, checkCertificateRevocation);
buffer = new byte[4];
int readBytes = _sslStream.Read(buffer, 0, 4);
if (readBytes == 0)
break;
int MessageSize = BitConverter.ToInt32(buffer, 0);
byte[] bufferreader = new byte[MessageSize];
clientSocket.ReceiveBufferSize = MessageSize;
readBytes = _sslStream.Read(bufferreader, 0, MessageSize);
Console.WriteLine(Convert.ToString(MessageSize));
rCount = Convert.ToString(requestCount);
dataFromClient = Encoding.ASCII.GetString(bufferreader);
byte[] outbuffer = new byte[4];
serverResponse = R.Respond(dataFromClient, K, clientSocket);
sendBytes = Encoding.ASCII.GetBytes(serverResponse);
outbuffer = new byte[4];
outbuffer = BitConverter.GetBytes(sendBytes.Length);
_sslStream.Write(outbuffer, 0, 4);
_sslStream.Flush();
clientSocket.SendBufferSize = sendBytes.Length;
MessageBox.Show(serverResponse);
_sslStream.Write(sendBytes, 0, sendBytes.Length);
_sslStream.Flush();
}
catch (Exception ex)
{
EndPointHandler.RemoveEndPoint(clientSocket);
clientSocket.Close();
Console.WriteLine("User Server >> " + ex.ToString());
Thread.CurrentThread.Abort();
}
}
EndPointHandler.RemoveEndPoint(clientSocket);
Console.WriteLine("User Server >> " + "Client No:" + Convert.ToString(clNo) + " Stopped!");
}
private bool ClientValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
switch (sslPolicyErrors)
{
case SslPolicyErrors.RemoteCertificateNameMismatch:
Console.WriteLine("Client's name mismatch. End communication ...\n");
return false;
case SslPolicyErrors.RemoteCertificateNotAvailable:
Console.WriteLine("Client's certificate not available. End communication ...\n");
return false;
case SslPolicyErrors.RemoteCertificateChainErrors:
Console.WriteLine("Client's certificate validation failed. End communication ...\n");
return false;
}
Console.WriteLine("Client's authentication succeeded ...\n");
return true;
}
private X509Certificate ServerCertificateSelectionCallback(object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
{
return ServerCertificate.Servercertificate();
}
Upvotes: 2
Views: 377
Reputation: 9806
In your Java code you have:
final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING);
Which likely means you are using PKCS5/7 Padding, unless you are just really terrible at picking names for your constants.
However, in your C# code, you have:
AES.Padding = PaddingMode.None;
Which is clearly not PKCS5/7 Padding... So you should probably change that to PaddingMode.PKCS7
.
EDIT: Please also don't disregard my comment about your IV. If you want your code to actually be worth using, you should automatically generate the IV for each encryption and prepend it to the ciphertext.
Also just noticed that you derive your key data in different ways. You are using PBKDF2 w/ SHA1 in C# (Rfc2898DeriveBytes
) but using a single iteration of SHA256 in Java. You'll need to pick one or another.
Upvotes: 2