AESEncoder class is not supported on j2me chinese phone - encryption

I am using this encryption class in a J2ME app. My J2ME application works fine on all Nokia devices. The app doesn't work on the Chinese MIw200 phone. Perhaps this cryptography is not supported on that phone? Is there another solution or any other method to encrypt and decrypt?
Please help me. Thanks a lot in advance.
My code is below:
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class AESEncoder {
private SecretKeySpec keyspec;
private Cipher cipher;
private String secretkey;
public AESEncoder(String secretkey) {
this.secretkey = secretkey;
keyspec = new SecretKeySpec(secretkey.getBytes(), 0, 16, "AES");
// keyspec=new SecretKeySpec(key, offset, len, secretkey);
try {
cipher = Cipher.getInstance("AES/ECB/NoPadding");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception {
if (text == null || text.length() == 0) {
throw new Exception("Empty string");
}
int encrypted = 0;
byte[] bytenc = null;//new byte[32];
byte[] input = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec);
// byte empty[]=padString(text).getBytes();
// encrypted = cipher.doFinal(padString(text).getBytes());
// encrypted=cipher.doFinal(padString(text).getBytes(), 0, 0, padString(text).getBytes(), 0);
input = padString(text).getBytes();
bytenc = new byte[input.length];
encrypted = cipher.doFinal(input, 0, input.length, bytenc, 0);
String str = new String(bytenc, 0, encrypted);
// encrypted=cipher.update(padString(text).getBytes(), 0, 0, 0, 0);
// System.out.println("Encrypted is:>>" + str);
// bytenc=hexToBytes(String.valueOf(encrypted));
} catch (Exception e) {
throw new Exception("[encrypt] " + e.getMessage());
}
return bytenc;
}
public String encrypt_hsm(String text) throws Exception {
if (text == null || text.length() == 0) {
throw new Exception("Empty string");
}
String base64=null;
int encrypted = 0;
byte[] bytenc = null;//new byte[32];
byte[] input = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec);
// byte empty[]=padString(text).getBytes();
// encrypted = cipher.doFinal(padString(text).getBytes());
// encrypted=cipher.doFinal(padString(text).getBytes(), 0, 0, padString(text).getBytes(), 0);
input = padString(text).getBytes();
bytenc = new byte[input.length];
encrypted = cipher.doFinal(input, 0, input.length, bytenc, 0);
String str = new String(bytenc, 0, encrypted);
base64 = Base64.encode(bytenc);
// encrypted=cipher.update(padString(text).getBytes(), 0, 0, 0, 0);
// System.out.println("Encrypted is:>>" + str);
// bytenc=hexToBytes(String.valueOf(encrypted));
} catch (Exception e) {
throw new Exception("[encrypt] " + e.getMessage());
}
return base64;
}
public byte[] decrypt(String code) throws Exception {
if (code == null || code.length() == 0) {
throw new Exception("Empty string");
}
int decrypted = 0;
byte[] bytedec = null;
byte[] input = null;
try {
cipher.init(Cipher.DECRYPT_MODE, keyspec);
// input=hexToBytes(code);
input = Base64ToBytes(code);
bytedec = new byte[input.length];
decrypted = cipher.doFinal(input, 0, input.length, bytedec, 0);
String str = new String(bytedec, 0, decrypted);
// System.out.println("Decrypted is:>>" + str);
} catch (Exception e) {
throw new Exception("[decrypt] " + e.getMessage());
}
return bytedec;
}
public static String bytesToHex(byte[] bsData) {
int nDataLen = bsData.length;
String sHex = "";
for (int nIter = 0; nIter < nDataLen; nIter++) {
int nValue = (bsData[nIter] + 256) % 256;
int nIndex1 = nValue >> 4;
sHex += Integer.toHexString(nIndex1);
int nIndex2 = nValue & 0x0f;
sHex += Integer.toHexString(nIndex2);
}
return sHex;
}
public static byte[] hexToBytes(String str) {
if (str == null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i = 0; i < len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
}
return buffer;
}
}
private static String padString(String source) {
char paddingChar = ' ';
int size = 32;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++) {
source += paddingChar;
}
// System.out.println("====>Pad String:" + source);
return source;
}
public void startApp() {
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
private byte[] Base64ToBytes(String code) {
code = code.replace('-', '+');
code = code.replace('_', '/');
code = code.replace(',', '=');
System.out.println("Final Base 64:"+code);
byte[] aesString = Base64.decode(code);
// System.out.println("Base64 after decoding:"+new String(aesString));
return aesString;
}
}

Please post a stack trace. Otherwise we are all just guessing.
AES is a required cipher, sometime between v4 and v7. Spend some time and confirm that this cipher isn't available on the MIw200.
Someone getting "AES not available" on a Mac got some suggestions.
Try allowing the system to fall back to 3DES or DES, instead of forcing AES. Here's an example that tests encryption with each algorithm.
Try using the BouncyCastle API. Here is a how-to guide.

Related

lHash mismatch error in decryption with HSM stored key

In decryption of encrypted key i receive lhash mismatch error. The key is encrypt with RSA/ECB/OAEPWithSHA-1AndMGF1Padding . I used PKCS#11 provider . this is my code. Please provide solution for this ..
public class DataDecryptorNew {
private static final int PUBLIC_KEY_SIZE = 294;
private static final int EID_SIZE = 32;
private static final int SECRET_KEY_SIZE = 256;
private static final String TRANSFORMATION2 = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
private static final String TRANSFORMATION3 = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
private static final String SECURITY_PROVIDER = "BC";
private static SunPKCS11 providerPKCS11;
private static String provider;
private static final String DIGEST_ALGORITHM = "SHA-256";
private static final String MASKING_FUNCTION = "MGF1";
private static final int VECTOR_SIZE = 16;
private static final int HMAC_SIZE = 32;
private static final int BLOCK_SIZE = 128;
private static final byte[] HEADER_DATA = "VERSION_1.0".getBytes();
private static final String SIGNATURE_TAG = "Signature";
private static final String MEC_TYPE = "DOM";
public static final String DLL = "C:\\pkcs11\\cknfast.dll";
public static String alias = "";
public static int keyLength = 2048;
private static final String password = "";
public static final String storeType = "PKCS11-nCipher";
private PrivateKey privateKey;
private PublicKey publicKey;
private KeyStore.PrivateKeyEntry keyEntry;
private KeyStore keyEntry1;
static {
Security.addProvider(new BouncyCastleProvider());
}
public byte[] decrypt(byte[] data) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IOException, CertificateException, Exception {
if (data == null || data.length == 0) {
throw new Exception("byte array data can not be null or blank array.");
}
PrivateKey key = getPrivateKey();
ByteArraySpliter arrSpliter = new ByteArraySpliter(data);
byte[] secretKey = decryptSecretKeyData(arrSpliter.getEncryptedSecretKey(), arrSpliter.getIv(), key);
byte[] plainData = decryptData(arrSpliter.getEncryptedData(), arrSpliter.getIv(), secretKey);
boolean result = validateHash(plainData);
if (!result) {
throw new Exception("Integrity Validation Failed : "
+ "The original data at client side and the decrypted data at server side is not identical");
}
return trimHMAC(plainData);
}
private KeyStore.PrivateKeyEntry getKeyFromFile(String keyStoreFile, char[] keyStorePassword) {
try {
// Load the KeyStore and get the signing key and certificate.
KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream keyFileStream = new FileInputStream(keyStoreFile);
ks.load(keyFileStream, keyStorePassword);
String alias = ks.aliases().nextElement();
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(keyStorePassword));
if (entry == null) {
throw new Exception("Key not found for the given alias.");
}
keyFileStream.close();
return entry;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static PrivateKey getPrivateKey() throws Exception {
String config = "name=nCipher\n"
+ "library=" + DLL + "\n"
+ "slotListIndex = 0 ";
ByteArrayInputStream bais = new ByteArrayInputStream(config.getBytes());
Provider p = new SunPKCS11(bais);
Security.addProvider(p);
KeyStore ks = KeyStore.getInstance("PKCS11", p);
ks.load(null, "".toCharArray());
System.out.println("Keystore size : " + ks.size());
String alias = "ncipher-cert/cn=(n)code solutions ca 2014,2.5.4.51=#13133330312c20474e464320496e666f746f776572,street=bodakdev\\, s g road\\, ahmedabad,st=gujarat,2.5.4.17=#1306333830303534,ou=certifying authority,o=gujarat narmada valley fertilizers and chemicals limited,c=in/1396768448";
KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(password.toCharArray());
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, protParam);
// get my private key
PrivateKey key = pkEntry.getPrivateKey();
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = ks.getCertificate(alias);
System.out.println(">>>>>>>>>" + ((X509Certificate) cert).getSerialNumber().toString(16));
// Get public key
PublicKey publicKey = cert.getPublicKey();
//Get Private Key
Key privatekey = (PrivateKey) key;
System.out.println("privatekey=" + privatekey);
}
return (PrivateKey) key;
}
private byte[] decryptSecretKeyData(byte[] encryptedSecretKey, byte[] iv) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, IOException, CertificateException, Exception {
try {
PrivateKey key = (PrivateKey) getPrivateKey();
System.out.println("Private Key:" + getPrivateKey().getFormat());
Cipher decCipher = Cipher.getInstance("RSA/ECB/NoPadding");
decCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decipheredText = null;
decipheredText = decCipher.doFinal(encryptedSecretKey);
System.out.println("OAEP padded plain text: " + Arrays.toString(decipheredText));
if (decipheredText.length < keyLength / 8) {
byte[] tmp = new byte[(keyLength / 8) - 42];
System.arraycopy(decipheredText, 0, tmp, tmp.length - decipheredText.length, decipheredText.length);
System.out.println("Zero padding to " + (keyLength / 8));
decipheredText = tmp;
}
PSource pSrc = (new PSource.PSpecified(new byte[256]));
OAEPParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, pSrc);
RSAPadding padding = RSAPadding.getInstance(RSAPadding.PAD_OAEP_MGF1, keyLength / 8, new SecureRandom(), paramSpec);
System.out.println("PaddedPlainText length: " + decipheredText.length); //256
byte[] plainText2 = padding.unpad(decipheredText, 0, decipheredText.length);
System.out.println("Unpadded plain text: " + DatatypeConverter.printHexBinary(plainText2));
System.out.println("Decrypted Value:" + new String(plainText2));
return plainText2;
} catch (GeneralSecurityException e) {
e.printStackTrace();
throw new Exception("Failed to decrypt AES secret key using RSA.", e);
}
}
private static class ByteArraySpliter {
private final byte[] headerVersion;
private final byte[] iv;
private final byte[] encryptedSecretKey;
private final byte[] encryptedData;
private final byte[] publicKeyData;
public ByteArraySpliter(byte[] data) throws Exception {
int offset = 0;
headerVersion = new byte[HEADER_DATA.length];
copyByteArray(data, 0, headerVersion.length, headerVersion);
offset = offset + HEADER_DATA.length;
publicKeyData = new byte[PUBLIC_KEY_SIZE];
copyByteArray(data, offset, publicKeyData.length, publicKeyData);
offset = offset + PUBLIC_KEY_SIZE;
iv = new byte[EID_SIZE];
copyByteArray(data, offset, iv.length, iv);
offset = offset + EID_SIZE;
encryptedSecretKey = new byte[SECRET_KEY_SIZE];
copyByteArray(data, offset, encryptedSecretKey.length, encryptedSecretKey);
offset = offset + SECRET_KEY_SIZE;
encryptedData = new byte[data.length - offset];
copyByteArray(data, offset, encryptedData.length, encryptedData);
}
public byte[] getIv() {
return iv;
}
public byte[] getEncryptedSecretKey() {
return encryptedSecretKey;
}
public byte[] getEncryptedData() {
return encryptedData;
}
private void copyByteArray(byte[] src, int offset, int length, byte[] dest) throws Exception {
try {
System.arraycopy(src, offset, dest, 0, length);
} catch (Exception e) {
throw new Exception("Decryption failed, Corrupted packet ", e);
}
}
}
private byte[][] split(byte[] src, int n) {
byte[] l, r;
if (src == null || src.length <= n) {
l = src;
r = new byte[0];
} else {
l = new byte[n];
r = new byte[src.length - n];
System.arraycopy(src, 0, l, 0, n);
System.arraycopy(src, n, r, 0, r.length);
}
return new byte[][]{l, r};
}
public byte[] generateHash(byte[] message) throws Exception {
byte[] hash = null;
try {
MessageDigest digest = MessageDigest.getInstance(DIGEST_ALGORITHM, SECURITY_PROVIDER);
digest.reset();
hash = digest.digest(message);
} catch (GeneralSecurityException e) {
throw new Exception("SHA-256 Hashing algorithm not available");
}
return hash;
}
public static void main(String[] args) throws Exception {
String var = "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";
CustomBase64 base64 = new CustomBase64();
DataDecryptorNew decryptor = new DataDecryptorNew();
decryptor.decrypt(Base64.decode(var.getBytes()));
}
}
The error which i received is following.
Exception in thread "main" javax.crypto.BadPaddingException: lHash mismatch
at in.gov.uidai.kyc.client.RSAPadding.unpadOAEP(RSAPadding.java:396)
at in.gov.uidai.kyc.client.RSAPadding.unpad(RSAPadding.java:244)
at in.gov.uidai.kyc.client.RSAPadding.unpad(RSAPadding.java:227)
at in.gov.uidai.kyc.client.AsymmetricEncryptionExample.performEncryptDecrypt(AsymmetricEncryptionExample.java:127)
at in.gov.uidai.kyc.client.AsymmetricEncryptionExample.main(AsymmetricEncryptionExample.java:68)
There are 2 things that i have noticed in your piece of code :-
While initializing the PSource don`t initialize "iv" parameter it again , instead use the argument value from the method .
So instead of using
`PSource pSrc = (new PSource.PSpecified(new byte[256]));`
try using
PSource pSrc = (new PSource.PSpecified(iv));
Also in the you are using SHA-256 , however while initializing OAEPParameterSpec used for OAEP padding , you are using SHA-1 instead of SHA-256 for MGF1ParameterSpec
So instead of using
OAEPParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, pSrc);
try using :-
OAEPParameterSpec paramSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, pSrc);
Hope this will work for you...
Cheers!!

Encryption / decryption for j2me app with AES 128 encryption using sha256 hashing

I have to use encryption / decryption mechanism for a j2me application and lots of searching I found that Bouncy Castle is most suitable for j2me apps.
Below are the steps that I follow to perform encryption:
Get a string needed to create a hash key using sha256 algorithm;
With that hash key perform AES-128 encryption for a plain text.
Below is the sample code. It is using key and IV (Initialization Vector) for encryption key generation. Is it same as sha256 hashing?
static String strEnc = "String for encryption";
final static String strPassword = "2345678978787878"; // AES 128 -
String encrypted;
public static String strEncResult;
public static String strDcrResult;
public static String keyStr;
String dcrtpt;
String enc1;
//Key key;
/*public static byte[] getSHA256(String key) {
SHA256Digest digester = new SHA256Digest();
byte[] retValue = new byte[digester.getDigestSize()];
digester.update(key.getBytes(), 0, key.length());
digester.doFinal(retValue, 0);
System.out.println("retValue === "+retValue);
return retValue;
}*/
public static byte[] cipherData(PaddedBufferedBlockCipher cipher,
byte[] data) throws Exception {
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
public static byte[] decrypt(byte[] cipher, byte[] key, byte[] iv)
throws Exception {
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key),
iv);
aes.init(false, ivAndKey);
return cipherData(aes, cipher);
}
public static byte[] encrypt(byte[] plain, byte[] key, byte[] iv)
throws Exception {
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key),
iv);
aes.init(true, ivAndKey);
return cipherData(aes, plain);
}
public static String encryptMe(String plain){
byte[] plainStr = plain.getBytes();
byte[] keyStr = strPassword.getBytes();//getSHA256(strPassword);
byte[] ivStr = strPassword.getBytes();//getSHA256(strPassword);
try {
byte[] encBytes = encrypt(plainStr, keyStr,
ivStr);
byte[] encbase = Base64.encode(encBytes);
strEncResult = new String(encbase, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return strEncResult;
}
public static String decryptMe(String encrtptedStr){
try {
byte[] dcrByte = Base64.decode(encrtptedStr.getBytes());
byte[] dec = decrypt(dcrByte, strPassword.getBytes()/*getSHA256(strPassword)*/,
strPassword.getBytes()/*getSHA256(strPassword)*/);
strDcrResult = new String(dec, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return strDcrResult;
}
protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException {
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
byte[] enc;
try {
enc = encrypt(strEnc.getBytes(), /*getSHA256(strPassword)*/strPassword.getBytes(),
/*getSHA256(strPassword)*/strPassword.getBytes());
byte[] encbase = Base64.encode(enc);
encrypted = new String(encbase, "UTF-8");
enc1= encryptMe ("String for encryption");
System.out.println("Encrypted is:" + encbase + "/// "+enc1);
} catch (Exception e) {
e.printStackTrace();
}
byte[] decbase = Base64.decode(encrypted.getBytes());
byte[] dec;
try {
dec = decrypt(decbase, /*getSHA256(strPassword)*/strPassword.getBytes(),
/*getSHA256(strPassword)*/strPassword.getBytes());
dcrtpt = decryptMe(enc1);
System.out.println("Decrypted file is:" + new String(dec, "UTF-8")+"///"+dcrtpt);
} catch (Exception e) {
e.printStackTrace();
}
}
i got it worked!!. i have used sha256 for secret key generation and took first 16 digit for AES 128 encryption. i am getting correct encrypted and decrypted data when it is 16 or below 16 string. if it is above 16 char string i am getting 16 char with some unwanted characters. (Eg: abcdefghijklmnop5#�D�!�&M�\~C��) can anybody help me to sort this issue. please see below for code
public static String getSHA256(String key) {
SHA256Digest digester = new SHA256Digest();
byte[] retValue = new byte[digester.getDigestSize()];
digester.update(key.getBytes(), 0, key.length());
digester.doFinal(retValue,0);
byteToStr = new String(Hex.encode(retValue));
System.out.println("byteToStr === " + byteToStr);
byteToStr = byteToStr.substring(0, 16);
System.out.println("byteToStr after subString === " + byteToStr);
return byteToStr;
}
public static byte[] cipherData(BufferedBlockCipher cipher, byte[] data)
throws Exception {
int minSize = cipher.getOutputSize(data.length);
System.out.println("min Size = "+minSize);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
System.out.println("length1 = "+length1 +"/ length2 = "+length2);
int actualLength = length1 + length2;
System.out.println("actualLength = "+actualLength);
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
public static byte[] decrypt(byte[] cipher, byte[] key/* , byte[] iv */)
throws Exception {
/*
* PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher( new
* CBCBlockCipher(new AESEngine())); CipherParameters ivAndKey = new
* ParametersWithIV(new KeyParameter(key), iv); aes.init(false,
* ivAndKey); return cipherData(aes, cipher);
*/
BufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
KeyParameter secretKey = new KeyParameter(key);
aes.init(false, secretKey);
return cipherData(aes, cipher);
}
public static byte[] encrypt(byte[] plain, byte[] key/* , byte[] iv */)
throws Exception {
/*
* PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher( new
* CBCBlockCipher(new AESEngine())); CipherParameters ivAndKey = new
* ParametersWithIV(new KeyParameter(key), iv);
*/
BufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
KeyParameter secretKey = new KeyParameter(key);
aes.init(true, secretKey);
return cipherData(aes, plain);
}
public static String encryptMe(String plain) {
byte[] plainStr = plain.getBytes();
byte[] keyStr = getSHA256(key).getBytes();
// byte[] ivStr = iv.getBytes();//
System.out.println("key str = "+Strings.fromByteArray(keyStr));
try {
byte[] encBytes = encrypt(plainStr, keyStr/*
* , ivStr
*/);
strEncResult= Base64.toBase64String(encBytes);
//strEncResult = new String(encbase);
} catch (Exception e) {
e.printStackTrace();
}
return strEncResult;
}
public static String decryptMe(String cipherText) {
try {
byte[] dcrByte = Base64.decode(cipherText);
byte[] dec = decrypt(dcrByte, getSHA256(key).getBytes()/*
* ,iv.getBytes
* ()
*/);
strDcrResult = Strings.fromByteArray(dec);
} catch (Exception e) {
e.printStackTrace();
}
return strDcrResult;
}

C# - TcpClient. Send data response after receive only works without iterate

My server receive some TCP/IP data and response to client:
private static void startClient(TcpClient clientSocket)
{
NetworkStream networkStream = null;
DateTime fecha = DateTime.Now;
try
{
clientSocket.NoDelay = true;
networkStream = clientSocket.GetStream();
string receiveData = readData(clientSocket);
string responseData = "abc"; //ProcessData(receiveData);
if (responseData != null)
writeData(networkStream, responseData);
}
catch (SocketException e)
{
throw;
}
finally
{
networkStream.Close();
}
}
private static string readData(TcpClient tcpClient)
{
try
{
var bytesFrom = new byte[tcpClient.ReceiveBufferSize];
StringBuilder dataFromClient = new StringBuilder();
int readCount;
while ((readCount = tcpClient.GetStream().Read(bytesFrom, 0, tcpClient.ReceiveBufferSize)) != 0)
{
dataFromClient.Append(Encoding.ASCII.GetString(bytesFrom, 0, readCount));
}
//int bytesRead = tcpClient.GetStream().Read(bytesFrom, 0, tcpClient.ReceiveBufferSize);
//string dataFromClient = Encoding.ASCII.GetString(bytesFrom, 0, bytesRead);
return dataFromClient.ToString();
}
catch (SocketException e)
{
throw;
}
}
private static void writeData(NetworkStream networkStream, string dataToClient)
{
Byte[] sendBytes = null;
try {
sendBytes = Encoding.ASCII.GetBytes(dataToClient);
networkStream.Write(sendBytes,0, sendBytes.Length);
networkStream.Flush();
}
catch(SocketException e)
{
throw;
}
}
With this solution the client never receives the response sent:
http://postimg.org/image/6srtslf2f/
However changing the reception to a single call to NetworkStream.Read ...
private static string readData(TcpClient tcpClient)
{
try
{
var bytesFrom = new byte[tcpClient.ReceiveBufferSize];
int bytesRead = tcpClient.GetStream().Read(bytesFrom, 0, tcpClient.ReceiveBufferSize);
string dataFromClient = Encoding.ASCII.GetString(bytesFrom, 0, bytesRead);
return dataFromClient.ToString();
}
catch (SocketException e)
{
throw;
}
}
... the client receives the response
http://postimg.org/image/uih9hadfr/
UPDATE
I found solution here. I´ve fixed it using 2/3 ways described . First handle EOS end message. Seccond is setting receive timeout if client works bad and sends bad data without EOS:
private static string readData(TcpClient tcpClient)
{
var clientStream = tcpClient.GetStream();
var dataFromClient = string.Empty;
var buffer = new byte[RECEIVE_BUFFER_SIZE];
if (!clientStream.CanRead)
return "";
tcpClient.ReceiveTimeout = RECEIVE_TIMEOUT;
try
{
int readCount;
while ((readCount = clientStream.Read(buffer, 0, buffer.Length)) != 0)
{
dataFromClient += Encoding.ASCII.GetString(buffer, 0, readCount);
if (dataFromClient.EndsWith(EOS))
return dataFromClient;
}
return dataFromClient.ToString();
}
catch (Exception ex)
{
var socketExept = ex.InnerException as SocketException;
if (socketExept != null && socketExept.SocketErrorCode == SocketError.TimedOut)
Logger.Warn(string.Format("Se excedio el timeout de recepcion: {0} ms",RECEIVE_TIMEOUT));
else
Logger.Error(string.Format("Error leyendo el mensaje recibido"), ex);
return dataFromClient.ToString();
}
}

wait() in asp.net (showing uploaded image)

I want to force my program to wait some moments after doing something, and then do somwthing else, in asp.net and silverlight.
(In Detail, I want to upload an image by silverlight program, and then show it in my page by an Image control. But when I upload images which their size is about 6KB or upper, the image doesn't show, however it has been uplaoded successfully. I think that waiting some moments may solve the problem)
May anyone guide me?
thank you
I use the code in this page
This is the code in MyPage.Xaml:
private void UploadBtn_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Multiselect = false;
dlg.Filter = UPLOAD_DIALOG_FILTER;
if ((bool)dlg.ShowDialog())
{
progressBar.Visibility = Visibility.Visible;
progressBar.Value = 0;
_fileName = dlg.File.Name;
UploadFile(_fileName, dlg.File.OpenRead());
}
else
{
//user clicked cancel
}
}
private void UploadFile(string fileName, Stream data)
{
// Just kept here
progressBar.Maximum = data.Length;
UriBuilder ub = new UriBuilder("http://mysite.com/receiver.ashx");
ub.Query = string.Format("fileName={0}", fileName);
WebClient c = new WebClient();
c.OpenWriteCompleted += (sender, e) =>
{
PushData(data, e.Result);
e.Result.Close();
data.Close();
};
try
{
c.OpenWriteAsync(ub.Uri);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
private void PushData(Stream input, Stream output)
{
byte[] buffer = new byte[input.Length];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, buffer.Length);
}
progressBar.Value += input.Length;
if (progressBar.Value >= progressBar.Maximum)
{
progressBar.Visibility = System.Windows.Visibility.Collapsed;
loadImage();
}
}
private void loadImage()
{
Uri ur = new Uri("http://mysite.com/upload/" + _fileName);
img1.Source = new BitmapImage(ur);
}
And this is receiver.ashx:
public void ProcessRequest(HttpContext context)
{
string filename = context.Request.QueryString["filename"].ToString(); using (FileStream fs = File.Create(context.Server.MapPath("~/upload/" + filename)))
{
SaveFile(context.Request.InputStream, fs);
}
}
private void SaveFile(Stream stream, FileStream fs)
{
byte[] buffer = new byte[stream.Length];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
fs.Write(buffer, 0, bytesRead);
}
}

How do encrypt a long or int using the Bouncy Castle crypto routines for BlackBerry?

How do encrypt/decrypt a long or int using the Bouncy Castle crypto routines for BlackBerry? I know how to encrypt/decrypt a String. I can encrypt a long but can't get a long to decrypt properly.
Some of this is poorly done, but I'm just trying stuff out at the moment.
I've included my entire crypto engine here:
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
public class CryptoEngine
{
// Global Variables
// Global Objects
private static AESFastEngine engine;
private static BufferedBlockCipher cipher;
private static KeyParameter key;
public static boolean setEncryptionKey(String keyText)
{
// adding in spaces to force a proper key
keyText += " ";
// cutting off at 128 bits (16 characters)
keyText = keyText.substring(0, 16);
keyText = HelperMethods.cleanUpNullString(keyText);
byte[] keyBytes = keyText.getBytes();
key = new KeyParameter(keyBytes);
engine = new AESFastEngine();
cipher = new PaddedBufferedBlockCipher(engine);
// just for now
return true;
}
public static String encryptString(String plainText)
{
try
{
byte[] plainArray = plainText.getBytes();
cipher.init(true, key);
byte[] cipherBytes = new byte[cipher.getOutputSize(plainArray.length)];
int cipherLength = cipher.processBytes(plainArray, 0, plainArray.length, cipherBytes, 0);
cipher.doFinal(cipherBytes, cipherLength);
String cipherString = new String(cipherBytes);
return cipherString;
}
catch (DataLengthException e)
{
Logger.logToConsole(e);
}
catch (IllegalArgumentException e)
{
Logger.logToConsole(e);
}
catch (IllegalStateException e)
{
Logger.logToConsole(e);
}
catch (InvalidCipherTextException e)
{
Logger.logToConsole(e);
}
catch (Exception ex)
{
Logger.logToConsole(ex);
}
// else
return "";// default bad value
}
public static String decryptString(String encryptedText)
{
try
{
byte[] cipherBytes = encryptedText.getBytes();
cipher.init(false, key);
byte[] decryptedBytes = new byte[cipher.getOutputSize(cipherBytes.length)];
int decryptedLength = cipher.processBytes(cipherBytes, 0, cipherBytes.length, decryptedBytes, 0);
cipher.doFinal(decryptedBytes, decryptedLength);
String decryptedString = new String(decryptedBytes);
// crop accordingly
int index = decryptedString.indexOf("\u0000");
if (index >= 0)
{
decryptedString = decryptedString.substring(0, index);
}
return decryptedString;
}
catch (DataLengthException e)
{
Logger.logToConsole(e);
}
catch (IllegalArgumentException e)
{
Logger.logToConsole(e);
}
catch (IllegalStateException e)
{
Logger.logToConsole(e);
}
catch (InvalidCipherTextException e)
{
Logger.logToConsole(e);
}
catch (Exception ex)
{
Logger.logToConsole(ex);
}
// else
return "";// default bad value
}
private static byte[] convertLongToByteArray(long longToConvert)
{
return new byte[] { (byte) (longToConvert >>> 56), (byte) (longToConvert >>> 48), (byte) (longToConvert >>> 40), (byte) (longToConvert >>> 32), (byte) (longToConvert >>> 24), (byte) (longToConvert >>> 16), (byte) (longToConvert >>> 8), (byte) (longToConvert) };
}
private static long convertByteArrayToLong(byte[] byteArrayToConvert)
{
long returnable = 0;
for (int counter = 0; counter < byteArrayToConvert.length; counter++)
{
returnable += ((byteArrayToConvert[byteArrayToConvert.length - counter - 1] & 0xFF) << counter * 8);
}
if (returnable < 0)
{
returnable++;
}
return returnable;
}
public static long encryptLong(long plainLong)
{
try
{
String plainString = String.valueOf(plainLong);
String cipherString = encryptString(plainString);
byte[] cipherBytes = cipherString.getBytes();
long returnable = convertByteArrayToLong(cipherBytes);
return returnable;
}
catch (Exception e)
{
Logger.logToConsole(e);
}
// else
return Integer.MIN_VALUE;// default bad value
}
public static long decryptLong(long encryptedLong)
{
byte[] cipherBytes = convertLongToByteArray(encryptedLong);
cipher.init(false, key);
byte[] decryptedBytes = new byte[cipher.getOutputSize(cipherBytes.length)];
int decryptedLength = cipherBytes.length;
try
{
cipher.doFinal(decryptedBytes, decryptedLength);
}
catch (DataLengthException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalStateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InvalidCipherTextException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
long plainLong = convertByteArrayToLong(decryptedBytes);
return plainLong;
}
public static boolean encryptBoolean(int plainBoolean)
{
return false;
}
public static boolean decryptBoolean(int encryptedBoolean)
{
return false;
}
public static boolean testLongToByteArrayConversion()
{
boolean returnable = true;
// fails out of the bounds of an integer, the conversion to long from byte
// array does not hold, need to figure out a better solution
for (long counter = -1000000; counter < 1000000; counter++)
{
long test = counter;
byte[] bytes = convertLongToByteArray(test);
long result = convertByteArrayToLong(bytes);
if (result != test)
{
returnable = false;
Logger.logToConsole("long conversion failed");
Logger.logToConsole("test = " + test + "\n result = " + result);
}
// regardless
}
// the end
Logger.logToConsole("final returnable result = " + returnable);
return returnable;
}
}
It's probably the conversion from long -> byte[] -> String, in particular the conversion from String back into byte[]. You don't pass in an encoding for String.getBytes() so it's going to be using the default character encoding, which may be altering your data.
My suggestion is to expose encrypt/decrypt methods that take byte[] as an argument, to avoid String/byte[] conversion.
Also, you may want to take a look at the native RIM AES classes, AESEncryptorEngine and AESDecryptorEngine which may be faster than BouncyCastle (since they're native APIs) and require less code.
I just realized that with strong ciphers, the result length is usually/always greater than the length of the original. If it wasn't, a lookup table could be used. As such, its not possible to encrypt a long into a long every time, especially if it uses all 64 bits. If this doesn't make sense, see me for more info:
How do I encrypt a string and get a equal length encrypted string?

Resources