J2ME TEA Encryption problem in older phones - encryption

Hey guys I'm having a huge problem when Encrypting a message in an older phone in comparison with the newer ones.
I've compiled the code to run on older hardware (CLDC1.0, MIDP2.0), and for some reason, when I do a TEA Encryption in a Nokia N70 I end up having one ruined character when it goes from plain-text to TEA. (yes I know, from a lot of chars only that one little char gets ruined...)
When I run exactly the same app on the N8 and other more recent phones however I get it encrypting correctly.
before I post the code however here's a small explanation on what it does:
basically it receives a String and a boolean inputs, the boolean states if it's for encryption or decryption purposes, whilst the string is what I want to encode or decode.
from there, I basically strip the String into a byte array, treat it accordingly (if for encrypt or decrypt) and later turn it into a String, which I then return (decrypt) or I encode in Base64 (encrypt).
The reason to encapsulate in Base64 is so it can be sent by sms, since this encoding uses non-special characters it keeps the sms limit up to 160 characters, which is desirable for the app.
now for the code:
private String HandleTEA(String input, boolean aIsEncryption) throws UnsupportedEncodingException
{
System.out.println(input);
String returnable = "";
try
{
TEAEngine e = new TEAEngine();
if (aIsEncryption)
{
e.init(true, TEAkey);
}
else
{
if(getDebug())
{
input = input.substring(1);
}
input = base64.decodeString(input);
e.init(false, TEAkey);
}
byte[] aData = input.getBytes("ISO-8859-1");
byte[] textToUse = aData;
int len = ((textToUse.length + 16 - 1) / 16) * 16;
byte[] secondUse = new byte[len];
for(int i = 0; i < textToUse.length; i++)
{
secondUse[i] = textToUse[i];
}
for(int i = textToUse.length; i < secondUse.length; i++)
{
secondUse[i] = 0;
}
int blockSize = e.getBlockSize();
byte[] outBytes = new byte[secondUse.length];
for (int chunkPosition = 0; chunkPosition < secondUse.length; chunkPosition += blockSize)
{
int chunkSize = Math.min(blockSize, (textToUse.length - (chunkPosition * blockSize)));
e.processBlock(secondUse, chunkPosition, outBytes, chunkPosition);
}
if(aIsEncryption)
{
Baseless = new String(outBytes, "ISO-8859-1");
String encodedString = base64.encodeString(Baseless);
char[] theChars = new char[encodedString.length()+1];
for(int i = 0; i < theChars.length; i++)
{
if(i == 0)
{
theChars[i] = '1';
}
else
{
theChars[i] = encodedString.charAt(i-1);
}
}
byte[] treating = new byte[theChars.length];
for(int i = 0; i < theChars.length; i++)
{
treating[i] = (byte)theChars[i];
}
returnable = new String(treating, "ISO-8859-1");
}
else
{
char[] theChars = new String(outBytes, "ISO-8859-1").toCharArray();
String fixed ="";
for(int i = 0; i < theChars.length; i++)
{
char c = theChars[i];
if (c > 0) fixed = fixed + c;
}
returnable = fixed;
}
}
catch(Exception e)
{
e.printStackTrace();
}
return returnable;
}
Anyone have any idea on what might be happening?
for comparison this is what I'm getting from the N70:
e+TgV/fU5RUOYocMRfG7vqpQT+jKlujU6eIzZfEjGhXdFwNB46wYNSiUj5H/tWbta26No6wjQylgTexhS6uqyw==
and from the N8:
e+TgV/fU5RUOYocMRfG7vqpQT+jKlujU6eIzZfEjgBXdFwNB46wYNSiUj5H/tWbta26No6wjQylgTexhS6uqyw==
as you can see everything looks similar, but in the middle of the code what gets encoded as Gh on the N70 shows up as gB on the N8...
when decrypting the data encrypted by the N70 we get some really weird chars:
will add this here tomorrow since I don't have the saved output with me
both are using the same key (in real-life tho they'll be using a key that's randomly generated on startup)
here's the key used:
0b1b5e0167aaee06
Hope you can help me out with this and Thanks for your interest and assistance!

your code is hard to understand, but Baseless = new String(outBytes, "ISO-8859-1"); and any similar constructs are almost certainly incorrect. Why do you want to make a String out of cipher? Just base64 encode outBytes directly.

Related

how to decrypt radius peap protocol client finish handshake message

i am using TLS_RSA_WITH_3DES_EDE_CBC_SHA cipher suite for the radius server, received a encrypted handshake message(40 bytes) right after ChangeCipherSpec from the client, i had tried to use 3des with cbc mode to decrypt those bytes, but with an exception(bad data), tried to look up the peap tls v1.0 on https://www.rfc-editor.org/rfc/rfc2246 but, didn't find a lot of infos about the finish handshake encryption/decryption in details. any help will be wonderful, thanks a lot!!
here are the code i used to compute the master secret and key materials.
public static byte[] ComputeMasterSecret(byte[] pre_master_secret, byte[] client_random, byte[] server_random)
{
byte[] label = Encoding.ASCII.GetBytes("master secret");
var seed = new List<byte>();
seed.AddRange(client_random);
seed.AddRange(server_random);
var master_secret = PRF(pre_master_secret, label, seed.ToArray(), 48);
return master_secret;
}
public static KeyMaterial ComputeKeys(byte[] master_secret, byte[] client_random, byte[] server_random)
{
/*
* The cipher spec which is defined in this document which requires
the most material is 3DES_EDE_CBC_SHA: it requires 2 x 24 byte
keys, 2 x 20 byte MAC secrets, and 2 x 8 byte IVs, for a total of
104 bytes of key material.
*/
byte[] label = Encoding.ASCII.GetBytes("key expansion");
var seed = new List<byte>();
seed.AddRange(client_random);
seed.AddRange(server_random);
byte[] key_material = PRF(master_secret, label, seed.ToArray(), 104); //need 104 for TLS_RSA_WITH_3DES_EDE_CBC_SHA cipher suite
var km = new KeyMaterial();
int idx = 0;
km.ClientWriteMACSecret = Utils.CopyArray(key_material, idx, 20);
idx += 20;
km.ServerWriteMACSecret = Utils.CopyArray(key_material, idx, 20);
idx += 20;
km.ClientWriteKey = Utils.CopyArray(key_material, idx, 24);
idx += 24;
km.ServerWriteKey = Utils.CopyArray(key_material, idx, 24);
idx += 24;
km.ClientWriteIV = Utils.CopyArray(key_material, idx, 8);
idx += 8;
km.ServerWriteIV = Utils.CopyArray(key_material, idx, 8);
return km;
}
public static byte[] PRF(byte[] secret, byte[] label, byte[] seed, int outputLength)
{
List<byte> s1 = new List<byte>();
List<byte> s2 = new List<byte>();
int size = (int)Math.Ceiling((double)secret.Length / 2);
for(int i=0;i < size; i++)
{
s1.Add(secret[i]);
s2.Insert(0, secret[secret.Length - i - 1]);
}
var tbc = new List<byte>();
tbc.AddRange(label);
tbc.AddRange(seed);
var md5Result = MD5Hash(s1.ToArray(), tbc.ToArray(), outputLength);
var sha1Result = SHA1Hash(s2.ToArray(), tbc.ToArray(), outputLength);
var result = new List<byte>();
for (int i = 0; i < outputLength; i++)
result.Add((byte)(md5Result[i] ^ sha1Result[i]));
return result.ToArray();
}
/// <summary>
/// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
/// HMAC_hash(secret, A(2) + seed) +
/// HMAC_hash(secret, A(3) + seed) + ...
/// Where + indicates concatenation.
/// A() is defined as:
/// A(0) = seed
/// A(i) = HMAC_hash(secret, A(i-1))
/// </summary>
/// <param name="secret"></param>
/// <param name="seed"></param>
/// <param name="iterations"></param>
/// <returns></returns>
private static byte[] MD5Hash(byte[] secret, byte[] seed, int outputLength)
{
int iterations = (int)Math.Ceiling((double)outputLength / 16);
HMACMD5 HMD5 = new HMACMD5(secret);
var result = new List<byte>();
byte[] A = null;
for (int i = 0; i <= iterations; i++)
if (A == null)
A = seed;
else
{
A = HMD5.ComputeHash(A);
var tBuff = new List<byte>();
tBuff.AddRange(A);
tBuff.AddRange(seed);
var tb = HMD5.ComputeHash(tBuff.ToArray());
result.AddRange(tb);
}
return result.ToArray();
}
private static byte[] SHA1Hash(byte[] secret, byte[] seed, int outputLength)
{
int iterations = (int)Math.Ceiling((double)outputLength / 20);
HMACSHA1 HSHA1 = new HMACSHA1(secret);
var result = new List<byte>();
byte[] A = null;
for (int i = 0; i <= iterations; i++)
if (A == null)
A = seed;
else
{
A = HSHA1.ComputeHash(A);
var tBuff = new List<byte>();
tBuff.AddRange(A);
tBuff.AddRange(seed);
var tb = HSHA1.ComputeHash(tBuff.ToArray());
result.AddRange(tb);
}
return result.ToArray();
}
The authentication/encryption and decryption/verification of the record containing the Finished handshake message are the same as all other records in SSL/TLS except that it is the first after CCS.
First (during handshake) the premaster secret from the keyexchange is used to derive a master secret and multiple working keys and IVs, depending on the suite. This varies a bit with the protocol version; for TLS1.0 see rfc2246 sections 8.1.1 (for plain RSA) 6.3 (for all keyexchanges) and 5.
Using a 'GenericBlock' (CBC) cipher -- which is the only option besides RC4 in TLS1.0 and 1.1 -- uses 6.2.3.1 fragmentation (not needed for this record) 6.2.3.2 optional compression (usually not used nowadays because of attacks like CRIME, and pretty useless for EAP traffic anyway) and 6.2.3.2.
Specifically, first an HMAC is added (for this suite HMAC-SHA1), then padding, then the result is encrypted using the data cipher (3DES-CBC) with an IV which for the first record (which Finished is) comes from the key derivation step above and for subsequent records comes from the last block of the previous record. (The latter is the flaw first reported by Rogaway and exploited by BEAST.)
Decryption and verification reverses this process in the obvious way. Note rfc2246 doesn't specify receiver must check all bytes of padding but this is apparently intended; rfc4346 (1.1) does specify it, without changing the content. (rfc4346 does change the IV handling to fix the Rogaway flaw. SSLv3 specified random padding except for the final length byte, so it can't be checked; this is the POODLE flaw.)
Some libraries/APIs that provide CBC mode for block ciphers (including 3DES) for arbitrary data default to PKCS5/7 padding. The padding TLS uses is similar to but NOT compatible with PKCS5/7 padding so using those libraries you may have to handle padding and unpadding yourself following the instructions in 6.2.3.2 -- or the code in any of about a dozen opensource TLS implementations.

convert byte[] to string when upload a file in asp.net

I have uploaded a file(image) by asp.net.
here is my code:
string imgpathpic =Convert .ToString (Session["imgpathpic"]);
long sizepic =Convert .ToInt64 (Session["sizepic"]);
string extpic = Convert.ToString(Session["extpic"]);
byte[] inputpic = new byte[sizepic - 1];
inputpic = FileUpload2.FileBytes;
for (int loop1 = 0; loop1 < sizepic; loop1++)
{
displayStringPic = displayStringPic + inputpic[loop1].ToString();
}
I converted byte[] to string by that for,but after line displayStringPic = displayStringPic + inputpic[loop1].ToString(); i receive this exception :
Index was outside the bounds of the array.
The loop condition would be on the length of inputpic as you are accessing the element of inputpic in the loop body
for (int loop1 = 0; loop1 < inputpic.Length; loop1++)
{
displayStringPic = displayStringPic + inputpic[loop1].ToString();
}
You should use string builder instead of string for optimum solution when there a lot of string concatenation, see How to: Concatenate Multiple Strings (C# Programming Guide)
StringBuilder sb = new StringBuilder();
foreach(byte b in inputpic)
{
sb.Append(b.ToString());
}
string displayStringPic = sb.ToString();
You better convert the byte array to string using System.Text.Encoding
var str = System.Text.Encoding.UTF8.GetString(result);
Note Aside from converting the byte array to string, you can story the image as Image or in binary format.

How to show HTTP response in Object Choice Field in Blackberry

I am reading a response from server using this code.
public static String getContentString(HttpConnection Connection) throws IOException
{
String Entity=null;
InputStream inputStream;
inputStream = Connection.openInputStream();//May give network io
StringBuffer buf = new StringBuffer();
int c;
while ((c = inputStream.read()) != -1)
{
buf.append((char) c);
}
//Response Formation
try
{
Entity = buf.toString();
return Entity;
}
catch(NullPointerException e)
{
Entity = null;
return Entity;
}
}
I need to show this Entity in object choice field.
For example:
suppose i get response Entity=ThisIsGoingToGood
then, I need to show below way in object choice drop down list.
This
Is
Going
To
Good
Please tell me how to achieve this.
This solution assumes:
The Camel Case format of your strings will always start with an upper case letter.
Only one upper case character in a row is used, even if the word is an acronym. For example, "HTTP response" would be written as "HttpResponse".
public static Vector getContentStrings(HttpConnection connection) throws IOException {
Vector words = new Vector();
InputStream inputStream = connection.openInputStream();
StringBuffer buf = new StringBuffer();
int c;
while ((c = inputStream.read()) != -1)
{
char character = (char)c;
if (CharacterUtilities.isUpperCase(character)) {
// upper case -> new word
if (buf.length() > 0) {
words.addElement(buf.toString());
buf = new StringBuffer();
}
}
buf.append(character);
}
// add the last word
words.addElement(buf.toString());
return words;
}
Then, you'll have a nice Vector full of the choices for your ObjectChoiceField. You can then insert() them, as shown in Signare's answer.
Note: always remember to close your streams, too. I've leave it to you to decide when you're really finished with it, though.
With ref from Nate's Answer- try this -
ObjectListField ol = new ObjectListField(ObjectListField.ELLIPSIS);
ol.setSize(words.size()); //Where words is the vector
for (int i = 0; i < size; i++)
{
ol.insert(i, words.elementAt(i));
}
add(ol);

Optimize a simple arithmetic which matches IP range

I want to check if an IP address is in a certain range, matching by "*" only. For example, "202.121.189.8" is in "202.121.189.*".
The scenario is that I have a list of banned IPs, some of them contains "*", so I wrote a function, it works fine so far:
static bool IsInRange(string ip, List<string> ipList)
{
if (ipList.Contains(ip))
{
return true;
}
var ipSets = ip.Split('.');
foreach (var item in ipList)
{
var itemSets = item.Split('.');
for (int i = 0; i < 4; i++)
{
if (itemSets[i] == "*")
{
bool isMatch = true;
for (int j = 0; j < i; j++)
{
if (ipSets[i - j - 1] != itemSets[i - j - 1])
{
isMatch = false;
}
}
if (isMatch)
{
return true;
}
}
}
}
return false;
}
Test code:
string ip = "202.121.189.8";
List<string> ipList = new List<string>() { "202.121.168.25", "202.121.189.*" };
Console.WriteLine(IsInRange(ip, ipList));
But I think what i wrote is very stupid, and I want to optimize it, does anyone have an idea how to simplify this function? not to use so many "for....if...".
A good idea would be to represent the banned subnets in a form of a pair: mask + base address. So your check will look like that:
banned = (ip & mask == baseaddress & mask);
For 11.22.33.* the base address will be 11*0x1000000 + 22*0x10000 + 33*0x100, mask will be 0xffffff00.
For single address 55.44.33.22 the address will be 55*0x1000000 + 44*0x10000 * 33*0x100 + 22, mask will be 0xffffffff.
You'll need to convert the address to a 32-bit int as a separate procedure.
After that all, your code will look like that:
int numip = ip2int(ip);
bool isIpBanned = banList.Any(item =>
numip & item.mask == item.baseaddress & item.mask);
By the way, this way you'll be able to represent even bans on smaller subsets.
int ip2int(string ip) // error checking omitted
{
var parts = ip.Split('.');
int result = 0;
foreach (var p in parts)
result = result * 0x100 + int.Parse(p);
}
class BanItem { public int baseaddres; public int mask; }
BanItem ip2banItem(string ip)
{
BanItem bi = new BanItem() { baseaddres = 0, mask = 0 };
var parts = ip.Split('.');
foreach (var p in parts)
{
bi.baseaddress *= 0x100;
bi.mask *= 0x100;
if (p != "*")
{
bi.mask += 0xff;
bi.baseaddress += int.Parse(p);
}
}
return bi;
}
banList = banIps.Select(ip2banItem).ToList();
I think you should keep a separate list for IP with * and those without asterick.
say IpList1 contains IP's without *
and
IpList2 --those contain * ..actually what we will be storing is the part before .* in this list. for e.g. 202.121.189.* would be stored as 202.121.189 only..
Thus for a given IP addrerss you just need to check for that IP address in IpList1,if it is not found over there then
for each Ip in IPList 2 you need to check whether it is a substring of input IP or not.
Thus no requirement of complex for and if loops.
Written In Java (Untested):
static boolean IsInRange(String ip, Vector<String> ipList) {
int indexOfStar = 0;
for (int i=0; i<ipList.size(); i++) {
if (ipList.contains("*")) {
indexOfStar = ipList.indexOf("*");
if ((ip.substring(0, indexOfStar)).equals(ipList.get(i).substring(0, indexOfStar))) {
return true;
}
}
}
return false;
}
I would use a space filling curve like in the xkcd comic: http://xkcd.com/195/. It's the function H(x,y) = (H(x),H(y)) and it reduces the 2 dimension to 1 dimension. It would also show that you are a real b*** coder.

Blackberry http connection reading contents of a webpage. Some punctuation marks are incorrectly read

I have a piece of code that opens a HTTP connection to read the data contained on a webpage.
HttpConnection h = new HttpConnection();
InputStream input = h.openInputStream();
int len = (int) h.httpConn.getLength();
StringBuffer raw = new StringBuffer();
if(len > 0)
{
byte[] data = new byte[len];
while( -1 != (len = input.read(data)))
{
raw.append(new String(data, 0, len));
}
}
response = raw.toString();
input.close();
h.httpConn.close();
//System.out.println("Response -----> " + response);
return response;
This code works absolutely fine, but on certain punctuation marks its not reading properly. For example >> ' << an apostrophe comes out as >> รข <<.
I'm guessing it might be something to do with encoding but I have tried UTF-8, UTF-16 and ASCII and this didn't fix the problem.
I've had this work for me when I was getting odd characters in place of punctuation:
public String getContents(InputStream stream) {
String contents = null;
try{
contents = new String(IOUtilities.streamToBytes(stream), "UTF-8");
}
catch(Exception e) {
//encoding error
}
return contents;
}
Instead of this:
raw.append(new String(data, 0, len));
you can use
raw.append(new String(data, 0, len, "UTF-8"));
passing in the name of a character enconding, in this case UTF-8.

Resources