parsing ASN files using bouncy castle - java

am trying to parse binary CDRs using JASN1
I have successfully generated Java classes using grammer file
not I have a CDR which I need to decode, but I can't get it to work, I don't understand what kind of inputs it requires
I have reached a point where I can parse CDR into lines like below
[1][[0]#01, [1]#26fd, [3]#4131002400, [8]#14040020236233, [9]#21436500000041, [10]#196105000045ffffffffffff, [13]#13900049999957, [14]#21436549999961, [15]#05, [16]#05, [17]#116102999954ffffffffffff, [22]#00a2, [23]#0001, [37]#0010, [38]#03, [40]#0324, [46]#06, [47]#05, [54]#00580720111220, [85]#04f4]
Java code
public class JASN1 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ByteArrayInputStream bais = new ByteArrayInputStream(readContentIntoByteArray(new File("sample.asn")));
ASN1InputStream ais = new ASN1InputStream(new FileInputStream(new File("sample.asn")));
while (ais.available() > 0) {
DERTaggedObject primitive = (DERTaggedObject) ais.readObject();
System.out.println(primitive.toASN1Object());
String encoded = toHexadecimal(new String(primitive.getEncoded()));
bais = new ByteArrayInputStream(encoded.getBytes());
MobileSampleMsg mobileSampleMsg = new MobileSampleMsg();
mobileSampleMsg.decode(bais, true);
System.out.println("MobileSampleMsg = " + mobileSampleMsg);
}
ais.close();
/*
* System.out.println(bais); MobileSampleMsg personnelRecord_decoded =
* new MobileSampleMsg(); personnelRecord_decoded.decode(bais, true);
*
* System.out.println("");
* System.out.println("PersonnelRecord.name.givenName = " +
* personnelRecord_decoded);
*/
}
private static byte[] readContentIntoByteArray(File file) {
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) file.length()];
try {
// convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return bFile;
}
public static String toHexadecimal(String text) throws UnsupportedEncodingException {
byte[] myBytes = text.getBytes("UTF-8");
return DatatypeConverter.printHexBinary(myBytes);
}
}
download samples from here
download grammer from here

I was able to encode/decode the file with the help of JASN1 and BouncyCastle, I used JASN1 to compile grammer file into java classes then used BouncyCastle to decode/encode new objects, below is code snippet used to show how I did that
public class BouncyCastle {
public static void main(String[] args) throws IOException {
DetailOutputRecord detailOutputRecord = new DetailOutputRecord();
MyRecord myRecord = new MyRecord();
myRecord.setOriginNodeType(new NodeType("xxxx".getBytes()));
myRecord.setTransactionAmount(new MoneyAmount("xxxx".getBytes()));
myRecord.setSubscriberNumber(new NumberString("xxxx".getBytes()));
ReverseByteArrayOutputStream ros = new ReverseByteArrayOutputStream(1000);
detailOutputRecord.setMyRecord(myRecord);
myRecord.encode(ros);
System.out.println(DatatypeConverter.printHexBinary(ros.getArray()));
System.out.println(print(ros.getArray()));
DERTaggedObject dermyRecord = new DERTaggedObject(false, 6, ASN1Primitive.fromByteArray(ros.getArray()));
File f = new File(String.valueOf("1_dermyRecord.ASN"));
FileOutputStream stream = new FileOutputStream(f);
try {
stream.write(dermyRecord.getEncoded());
} finally {
stream.close();
}
ros = new ReverseByteArrayOutputStream(1000);
detailOutputRecord.encode(ros);
DLSequence ddetailOutputRecord = new DLSequence(ASN1Primitive.fromByteArray(ros.getArray()));
stream = new FileOutputStream(new File("detailOutputRecord.ASN"));
try {
stream.write(ros.buffer);
} finally {
stream.close();
}
}
public static String print(byte[] bytes) {
StringBuilder sb = new StringBuilder();
sb.append("[ ");
for (byte b : bytes) {
// sb.append(String.format("0x%02X ", b));
sb.append(String.format("\\x%02X", b));
}
sb.append("]");
return sb.toString();
}
private static DERTaggedObject toDERObject(byte[] data) throws IOException {
ByteArrayInputStream inStream = new ByteArrayInputStream(data);
ASN1InputStream asnInputStream = new ASN1InputStream(inStream);
return (DERTaggedObject) asnInputStream.readObject();
}
}

Here is alternative way of processing given binary record files using org.bouncycastle.asn1 package only :
/*Sequence Tags */
static final int MSCRecordType = 0;
static final int RecordNumber = 1;
static final int RecordStatus = 3;
static final int CallingImsi = 8;
static final int CallingImei = 9;
void process() throws IOException, ClassNotFoundException {
String path = System.getProperty("user.dir") + "/telconetqual_sampledata/CDR_RGN0_20121120081859.asn";
File file = new File(path);
byte[] bFile = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(bFile);
ASN1InputStream in = new ASN1InputStream(bFile);
while (in.available() > 0) {
ASN1Primitive primitive = in.readObject();
DERTaggedObject derTaggedObject = (DERTaggedObject) primitive;
DLSequence sequence = (DLSequence)derTaggedObject.getObject();
for(int i =0; i < sequence.size(); i++){
DERTaggedObject seqElement = (DERTaggedObject)sequence.getObjectAt(i);
switch (seqElement.getTagNo()) {
case MSCRecordType:
DEROctetString recordTypeOctet =(DEROctetString)seqElement.getObject();
int recordType = Integer.valueOf(Hex.toHexString(recordTypeOctet.getOctets()));
break;
case CallingImsi:
DEROctetString CallingImsiOctet =(DEROctetString)seqElement.getObject();
String CallingImsi = Hex.toHexString(CallingImsiOctet.getOctets());
...
}
}
}
}

Related

Why does C# and Java application calculate different MD5 values for the same file?

I have a C# project to verify a file's MD5. I use System.Security.Cryptography.MD5 to calculate the MD5 in C#.
But it is different from the MD5 in Java.
EDIT: I have found the c# code is correct one. Thanks to Andy. May I know how to correct the Java code?
C# code:
public static String ComputeMD5(String fileName)
{
String hashMD5 = String.Empty;
if (System.IO.File.Exists(fileName))
{
using (System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
System.Security.Cryptography.MD5 calculator = System.Security.Cryptography.MD5.Create();
Byte[] buffer = calculator.ComputeHash(fs);
calculator.Clear();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < buffer.Length; i++){
stringBuilder.Append(buffer[i].ToString("x2"));
}
hashMD5 = stringBuilder.ToString();
}
}
return hashMD5;
}
Java Code:
public static String ComputeMD5(File file) {
if (!file.isFile()) {
return null;
}
MessageDigest digest = null;
FileInputStream in = null;
byte buffer[] = new byte[1024];
int len;
try {
digest = MessageDigest.getInstance("MD5");
in = new FileInputStream(file);
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bytesToHexString(digest.digest());
}
Your bytesToHexString function is wrong. After using the function from here, in this complete example, I get the same result as the Linux md5sum command and`onlinemd5.com as Andy suggested. The best way to handle this is to use a library, such as Apache Commons, that has a function to convert from bytes to a hex string. That way, you offload the work to get it right to a reputable library.
import java.io.File;
import java.io.FileInputStream;
import java.security.MessageDigest;
public class Md5{
public static String computeMd5(File file) {
if (!file.isFile()) {
return null;
}
MessageDigest digest = null;
FileInputStream in = null;
byte buffer[] = new byte[1024];
int len;
try {
digest = MessageDigest.getInstance("MD5");
in = new FileInputStream(file);
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return byteArrayToHex(digest.digest());
}
public static String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b));
return sb.toString();
}
public static void main(String[] args){
System.out.println(computeMd5(new File("./text.txt")));
}
}

Failed to upload WordPress media files using XML-RPC

This is my code.
public void fileUpload() throws Exception {
byte fileByte[] =org.apache.commons.io.FileUtils.readFileToByteArray(new File(path+realName));
String wpUpFile=fileToString(new File(path+realName));
XmlRpcClient blog = new XmlRpcClient();
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
Hashtable<String, String> post = new Hashtable<>();
Vector<Serializable> params = new Vector<Serializable>();
config.setServerURL(url);
config.setBasicUserName(user);
config.setBasicPassword(pw);
params.addElement(id);
params.addElement(user);
params.addElement(pw);
post.put("name", realName);
post.put("type", "image/jpeg");
post.put("bits", wpUpFile);
post.put("overwrite", "false");
params.addElement(post);
params.addElement(true);
Object blogPostID = blog.execute(config, "wp.uploadFile", params);
}
file base64 change code
public String fileToString(File file) throws IOException {
String fileString = new String();
FileInputStream inputStream = null;
ByteArrayOutputStream byteOutStream = null;
try {
inputStream = new FileInputStream(file);
byteOutStream = new ByteArrayOutputStream();
int len = 0;
byte[] buf = new byte[1024];
while ((len = inputStream.read(buf)) != -1) {
byteOutStream.write(buf, 0, len);
}
byte[] fileArray = byteOutStream.toByteArray();
fileString = new String(Base64.encodeBase64(fileArray));
} catch (IOException e) {
e.printStackTrace();
} finally {
inputStream.close();
byteOutStream.close();
}
return fileString;
}
result
The image file was not displayed properly. What is the problem?
It expects binary data of the raw image. Shouldn't be base64 encoded. bits parameter should be byte[] only. Don't convert to String.
inputStream = new FileInputStream(file);
byte[] bits = IOUtils.toByteArray(inputStream);
Hope you are already using org.apache.commons.io.IOUtils - in your code wpUpFile should just be byte[] bits.

Display Image in Header of Word Document Generated by Docx4j

am using Docx4j to generate a word document in a swing application.I want to add a picture to the header. The document is created successfully but the picture is not displayed. Below is the code snippets of the applications. I am using the docx4j-nightly-20141016.jar file.
import org.docx4j.wml.ObjectFactory;
public class WordDoc {
private WordprocessingMLPackage wordMLPackage;
private ObjectFactory factory;
private Hdr header;
public WordDoc() {
}
public void createWordDoc() throws Docx4JException, IOException, Exception {
wordMLPackage = WordprocessingMLPackage.createPackage();
factory = Context.getWmlObjectFactory();
Relationship relationship = createHeaderPart();
createHeaderReference(relationship);
wordMLPackage.getMainDocumentPart().addParagraphOfText("Hello Word!");
File file = new File("src/resources/images/logo.jpg");
byte[] bytes = convertImageToByteArray(file);
addImageInline(bytes);
wordMLPackage.save(new java.io.File("src/files/HelloWord14.docx"));
}
private Relationship createHeaderPart() throws InvalidFormatException {
HeaderPart headerPart = new HeaderPart();
headerPart.setPackage(wordMLPackage);
headerPart.setJaxbElement(createHeader("Text"));
return wordMLPackage.getMainDocumentPart().addTargetPart(headerPart);
}
private Hdr createHeader(String content) {
header = factory.createHdr();
P paragraph = factory.createP();
R run = factory.createR();
Text text = new Text();
text.setValue(content);
run.getContent().add(text);
paragraph.getContent().add(run);
header.getContent().add(paragraph);
return header;
}
private void createHeaderReference(Relationship relationship) {
List<SectionWrapper> sections
= wordMLPackage.getDocumentModel().getSections();
SectPr sectionProperties = sections.get(sections.size() - 1).getSectPr();
// There is always a section wrapper, but it might not contain a sectPr
if (sectionProperties == null) {
sectionProperties = factory.createSectPr();
wordMLPackage.getMainDocumentPart().addObject(sectionProperties);
sections.get(0).setSectPr(sectionProperties);
}
HeaderReference headerReference = factory.createHeaderReference();
headerReference.setId(relationship.getId());
headerReference.setType(HdrFtrRef.DEFAULT);
sectionProperties.getEGHdrFtrReferences().add(headerReference);
}
private byte[] convertImageToByteArray(File file)
throws FileNotFoundException, IOException {
InputStream is = new FileInputStream(file);
long length = file.length();
// You cannot create an array using a long, it needs to be an int.
if (length > Integer.MAX_VALUE) {
System.out.println("File too large!!");
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length -
offset)) >= 0) {
offset += numRead;
}
// Ensure all the bytes have been read
if (offset < bytes.length) {
System.out.println("Could not completely read file "
+ file.getName());
}
is.close();
return bytes;
}
private void addImageInline(byte[] bytes) throws Exception {
BinaryPartAbstractImage imagePart
= BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);
int docPrId = 1;
int cNvPrId = 2;
Inline inLine = imagePart.createImageInline("Filename hint",
"Alternative text", docPrId, cNvPrId, false);
if (header != null) {
addInlineImageToHeader(inLine);
}
}
private void addInlineImageToHeader(Inline inline) {
// Now add the in-line image to a paragraph
ObjectFactory factory2 = new ObjectFactory();
P paragraph2 = factory2.createP();
R run = factory.createR();
paragraph2.getContent().add(run);
Drawing drawing = factory.createDrawing();
run.getContent().add(drawing);
drawing.getAnchorOrInline().add(inline);
header.getContent().add(paragraph2);
}
}
the screen capture of the generated word document is displayed below
Will be very glad to take any suggestions.
Instead of:
BinaryPartAbstractImage imagePart
= BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);
you need to add the image part as a rel of your header part, so use:
public static BinaryPartAbstractImage createImagePart(
OpcPackage opcPackage,
Part sourcePart, byte[] bytes) throws Exception
passing it headerPart

Java - user-mapped section open error

When I try to write to the file specified it comes up with the error below. I have tried closing the FileInputStream but I still come up with the same problem.
Here is the relevant code:
Error log:
Error: C:\Path\Hours Log.csv (The requested operation cannot be performed on a file with a user-mapped section open)
Code:
Creating the log:
private void writeLog() throws IOException{
//set up vars and write directories
File yearStatDir = new File("C:\\Path);
File yearStatPath = new File(yearStatDir + "\\" + "Hours Log.csv");
String yearStatString = yearStatPath.toString();
//read the files
String existingYearLog = readLogFile(yearStatString, yearStatPath);
//write the updated file
String hoursString = "1";
String dataYear = existingYearLog + hoursString;
String folderYear = "Satistics\\Yearly data\\" + yearString;
writeFile(dataYear, ".csv", folderYear, "Hours Log");
}
Writing the file:
private void writeFile(String data, String fileType, String folder, String fileName){
try{
File fileDir = new File("C:\\Path\\" + folder);
File filePath = new File(fileDir + "\\"+ fileName + fileType);
writeDir(fileDir);
// Create file
FileWriter fstream = new FileWriter(filePath);
try (BufferedWriter out = new BufferedWriter(fstream)) {
out.write(data);
}
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
Reading the file:
private static String readLogFile(String path, File f) throws IOException {
if (f.exists()){
try (FileInputStream stream = new FileInputStream(new File(path))) {
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
/* Instead of using default, pass in a decoder. */
fc.close();
return Charset.defaultCharset().decode(bb).toString();
}
}
else {
return "";
}
}
For anyone that comes across this, here is the alternative code that I am using now:
private static String readLogFile(String path) throws IOException {
File f = new File(path);
if(f.exists()) {
FileInputStream fis = new FileInputStream(f);
Integer fileLength = (int) (long) f.length();
byte[] b = new byte[fileLength];
int read = 0;
while (read < b.length) {
read += fis.read(b, read, b.length - read);
}
String text = new String(b);
return text;
} else {
String text = "";
return text;
}
}

Android: decompress string that was compressed with PHP gzcompress()

How can i decompress a String that was zipped by PHP gzcompress() function?
Any full examples?
thx
I tried it now like this:
public static String unzipString(String zippedText) throws Exception
{
ByteArrayInputStream bais = new ByteArrayInputStream(zippedText.getBytes("UTF-8"));
GZIPInputStream gzis = new GZIPInputStream(bais);
InputStreamReader reader = new InputStreamReader(gzis);
BufferedReader in = new BufferedReader(reader);
String unzipped = "";
while ((unzipped = in.readLine()) != null)
unzipped+=unzipped;
return unzipped;
}
but it's not working if i i'm trying to unzip a PHP gzcompress (-ed) string.
PHP's gzcompress uses Zlib NOT GZIP
public static String unzipString(String zippedText) {
String unzipped = null;
try {
byte[] zbytes = zippedText.getBytes("ISO-8859-1");
// Add extra byte to array when Inflater is set to true
byte[] input = new byte[zbytes.length + 1];
System.arraycopy(zbytes, 0, input, 0, zbytes.length);
input[zbytes.length] = 0;
ByteArrayInputStream bin = new ByteArrayInputStream(input);
InflaterInputStream in = new InflaterInputStream(bin);
ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
int b;
while ((b = in.read()) != -1) {
bout.write(b); }
bout.close();
unzipped = bout.toString();
}
catch (IOException io) { printIoError(io); }
return unzipped;
}
private static void printIoError(IOException io)
{
System.out.println("IO Exception: " + io.getMessage());
}
Try a GZIPInputStream. See this example and this SO question.
See
http://developer.android.com/reference/java/util/zip/InflaterInputStream.html
since the DEFLATE algorithm is gzip.

Categories