/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package ticert;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author SLO
*/
public class TiCert {
private static List<Field> fields=new ArrayList<Field>();
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
if(args.length!=1) {
System.out.println("need a filename");
return;
}
String fname=args[0];
System.out.println("Opening "+fname+"...");
DataInputStream di=null;
try {
di = new DataInputStream(new FileInputStream(fname));
manage(di);
} catch (FileNotFoundException ex) {
System.out.println("not found");
} catch(EOFException ex) {
System.out.println("End of file.");
} catch(IOException ex) {
System.out.println("Read error, abort!");
} finally {
try {
di.close();
} catch(Exception ex) {}
}
}
private static String readFixedLengthString(DataInputStream di, int len) throws IOException {
byte[] b= new byte[len];
di.readFully(b);
return new String(b).trim();
}
private static void manage(DataInputStream di) throws IOException {
//skip tifile header
String h=readFixedLengthString(di,8);
System.out.println("header: "+h);
int by;
by=di.readUnsignedByte();if(by!=0x01) System.out.printf("warning(1), expected 0x01, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x00) System.out.printf("warning(2), expected 0x00, unexpected value %02X\n",by);
//decode cert mem
String folder=readFixedLengthString(di, 8);
System.out.println("Folder name:"+folder);
String comment=readFixedLengthString(di, 40);
System.out.println("Comment:"+comment);
by=di.readUnsignedByte();if(by!=0x01) System.out.printf("warning(3), expected 0x01, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x00) System.out.printf("warning(4), expected 0x00, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x52) System.out.printf("warning(5), expected 0x52, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x00) System.out.printf("warning(6), expected 0x00, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x00) System.out.printf("warning(7), expected 0x00, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x00) System.out.printf("warning(8), expected 0x00, unexpected value %02X\n",by);
String var=readFixedLengthString(di, 8);
System.out.println("Var name:"+var+" (should be certdump)");
by=di.readUnsignedByte();
System.out.printf("var type: 0x%02X\n",by);
by=di.readUnsignedByte();if((by&0xfc)!=0x00) System.out.printf("warning(10), expected 0x00, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x00) System.out.printf("warning(11), expected 0x00, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x00) System.out.printf("warning(12), expected 0x00, unexpected value %02X\n",by);
di.skipBytes(4); //pointer to eof
by=di.readUnsignedByte();if(by!=0xa5) System.out.printf("warning(13), expected 0xa5, unexpected value %02X\n",by);
by=di.readUnsignedByte();if(by!=0x5a) System.out.printf("warning(14), expected 0x5a, unexpected value %02X\n",by);
//now read data!
readcert(di);
Field mod=findField(0x020);
if(mod==null) {
System.out.println("modulus not found");
return;
}
System.out.printf("Modulus length: %d\n",mod.getLength()*8);
BigInteger b=new BigInteger(1, mod.getData());
System.out.println("Modulus:");
System.out.println(b.toString());
}
private static void readcert(DataInputStream di) throws IOException {
System.out.println("now reading certificate");
//skip 10 bytes header
di.skipBytes(10);
boolean ok=true;
while(ok) {
int tag=di.readUnsignedShort();
int lencode=tag&0x0F;
int len;
tag = tag>>>4;
System.out.printf("tag=0x%03X\n",tag);
if(lencode<=0x0C) {
len=lencode;
} else if(lencode==0x0D) {
len=di.readUnsignedByte();
} else if(lencode==0x0E) {
len=di.readUnsignedShort();
} else {
System.out.println("reading extra long fields is not supported, this is eof");
return;
}
System.out.printf("len=%d\n",len);
try {
Field f=new Field(tag,len,di);
fields.add(f);
} catch(EOFException ex) {
ok=false;
}
}
}
private static Field findField(int tag) {
for(Field f:fields) {
if(f.getTag()==tag) return f;
}
return null;
}
private static class Field {
private int tag;
private int len;
private byte[] data;
public Field(int tag, int len, DataInputStream d) throws IOException {
this.tag=tag;
this.len=len;
data=new byte[len];
d.readFully(data);
}
public int getTag() {
return tag;
}
public int getLength() {
return len;
}
public byte[] getData() {
return data;
}
}
}
/*
http://www.ticalc.org/cgi-bin/zipview?text/calcinfo/file_format.zip;file_format/ti89_92_92+/ti89_92_92+.txt
Adress What It Contains
---------------------------------------------------------------
0x00-0x07 0-7 **TI92** or **TI92P*
0x08-0x09 8-9 0x01 0x00
0x0A-0x11 10-17 folder name (8 chars)
0x12-0x39 18-57 comment (40 chars)
0x3A-0x3B 58-59 0x01 0x00 (number of vars: 1)
0x3C-0x3F 60-63 0x52 0x00 0x00 0x00 (1)
0x40-0x47 64-71 varname (8 chars)
0x48-0x49 72-73 vartype 0x00
0x4A-0x4B 74-75 0x00 0x00
0x4C-0x4F 76-79 (2)
0x50-0x51 80-81 0xA5 0x5A
0x52-0x.. 82-(n-1) data (raw data part)
0x..-0x.. n-(n+1) checksum (raw data part)
*/