|
/* applet to serve as an s/key calculator application wrapper
* around otp class.
*
* Copyright 1996, Harry Mantakos, harry@cs.umd.edu
*/
import java.awt.Button;
import java.awt.Color;
import java.awt.Event;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.util.StringTokenizer;
public class jotp extends java.applet.Applet {
TextField otptf, chaltf, pwtf;
final String md4label = "compute with MD4";
final String md5label = "compute with MD5";
final String version = "jotp 0.8";
/* Just takes challenge info and passphrase info on the
* command line (ick) and spits out the resulting otp "words".
*
* Mainly for testing.
*/
public static void main(String[] argv) {
String seed, passphrase;
int seq;
otp otpwd;
int hashalg;
String hashtype;
if ((argv.length < 3) || (argv.length > 4)) {
System.err.println("usage: jotp sequence seed passphrase" +
"[md4|md5]");
return;
}
seq = new Integer(argv[0]).intValue();
seed = new String(argv[1]);
passphrase = new String(argv[2]);
if ((argv.length == 3) || argv[3].equals("4") ||
argv[3].equals("md4") || argv[3].equals("MD4")) {
hashtype = "md4";
hashalg = otp.MD4;
} else if (argv[3].equals("5") || argv[3].equals("md5") ||
argv[3].equals("MD5")) {
hashtype = "md5";
hashalg = otp.MD5;
} else {
System.err.println("usage: jotp sequence seed passphrase " +
"[4|md4|5|md5]");
return;
}
otpwd = new otp(seq, seed, passphrase, hashalg);
System.out.println("Using " + hashtype + ". Thinking...");
otpwd.calc();
System.out.println(otpwd);
}
public void init() {
setBackground(Color.white);
setLayout(new GridLayout(6,1));
Panel panel1 = new Panel();
add (panel1);
Font titlefont = new Font("TimesRoman", Font.BOLD, 14);
panel1.setFont(titlefont);
panel1.add(new Label(String.valueOf(version) +
": The Java OTP (aka S/Key) calculator!"));
Panel panel2 = new Panel();
panel2.setLayout(new FlowLayout());
add (panel2);
panel2.add(new Label("Challenge (e.g. \"55 latour1\"):"));
chaltf = new TextField(24);
panel2.add(chaltf);
Panel panel3 = new Panel();
panel3.setLayout(new FlowLayout());
add(panel3);
panel3.add(new Label("Secret Password:"));
pwtf = new TextField(24);
pwtf.setEchoCharacter('*');
panel3.add(pwtf);
Panel panel4 = new Panel();
panel4.setLayout(new FlowLayout());
add(panel4);
panel4.add (new Button(String.valueOf(md4label)));
panel4.add (new Button(String.valueOf(md5label)));
Panel panel6 = new Panel();
panel6.setLayout(new FlowLayout());
add(panel6);
panel6.add(new Label("One-Time Password:", Label.LEFT));
otptf = new TextField(40);
panel6.add(otptf);
Panel panel7 = new Panel();
add(panel7);
panel7.add(new Label("jotp by Harry Mantakos, " +
"http://www.cs.umd.edu/~harry/jotp"));
}
public boolean action(Event evt, Object arg) {
String tmpstr, tmpstr2, seed, passphrase;
int seq, hashalg;
otp otpwd;
if (evt.target instanceof Button) {
if (arg.equals(md5label)) {
hashalg = otp.MD5;
} else {
hashalg = otp.MD4;
}
/* Split up challenge */
tmpstr = chaltf.getText();
StringTokenizer st = new StringTokenizer(tmpstr);
if (st.countTokens() != 2) {
otptf.setText("bogus challenge");
return true;
}
tmpstr2 = st.nextToken();
try {
seq = (Integer.parseInt(tmpstr2));
} catch (NumberFormatException e) {
otptf.setText("bogus sequence number '" + tmpstr2 + "'");
return true;
}
seed = st.nextToken();
passphrase = pwtf.getText();
/* passphrase = "eat me";*/
System.out.println("passphrase = " + passphrase);
otptf.setText("Okay, thinking...");
otpwd = new otp(seq, seed, passphrase, hashalg);
otpwd.calc();
otptf.setText(otpwd.toString());
}
return true;
}
}
/* Class for implementing OTP (aka s/key) one-time password calculation
* using the accompanying md class for md4 (and hopefully md5 eventually)
* based key calculation.
*
* The constructor is used to set the challenge info and passphrase,
* and the calc() method calculates the otp. The results can either
* be retrieved using the tolong() method, which gives you the 64 bits
* "folded" hash in a single word, or else as a String of otp "words"
* via toString().
*
* Cripes this is slow. How can we make it faster?
*
* Copyright 1996 Harry Mantakos, harry@cs.umd.edu
*/
class otp {
int seq;
String seed, passphrase;
byte hash[];
int sha;
final static byte MD4 = 4;
final static byte MD5 = 5;
otp(int n, String s, String p, int hashalg) {
this.seq = n;
this.seed = s;
this.passphrase = p;
this.sha = hashalg;
}
void calc() {
if (this.sha == MD5) {
this.md5calc();
} else {
this.md4calc();
}
}
void md4calc() {
int tmpseq = this.seq;
md4 mdc;
mdc = new md4(this.seed + this.passphrase);
mdc.calc();
this.hash = otpfoldregs(mdc.getregs());
while (tmpseq > 0) {
mdc = new md4(hash);
mdc.calc();
this.hash = otpfoldregs(mdc.getregs());
tmpseq--;
}
}
void md5calc() {
int tmpseq = this.seq;
md5 mdc;
mdc = new md5(this.seed + this.passphrase);
mdc.calc();
this.hash = otpfoldregs(mdc.getregs());
while (tmpseq > 0) {
mdc = new md5(hash);
mdc.calc();
this.hash = otpfoldregs(mdc.getregs());
tmpseq--;
}
}
static byte[] otpfoldregs(int regs[]) {
int ac, bd, i;
byte fold[] = new byte[8];
ac = regs[0] ^ regs[2];
bd = regs[1] ^ regs[3];
for (i=0; i < 4; i++) {
fold[i] = (byte) (ac & 0xff);
ac >>= 8;
}
for (i=4; i < 8; i++) {
fold[i] = (byte) (bd & 0xff);
bd >>= 8;
}
return fold;
}
long tolong() {
long wi;
int i;
wi = 0;
for (i=0; i < 8; i++) {
wi <<= 8;
wi |= (this.hash[i] & 0xff);
}
return wi;
}
public String toString() {
long wi, tmplong;
String tmpstr;
int i, j;
byte parity;
wi = this.tolong();
tmplong = wi;
tmpstr = "";
parity = 0;
for (i = 0; i < 64; i+=2) {
parity += tmplong & 0x3;
tmplong >>= 2;
}
for (i=4; i >= 0; i--) {
tmpstr += btoe((int)
((wi >> (i * 11 + 9)) & 0x7ff)) + " ";
}
tmpstr += btoe((int) ((wi << 2) & 0x7fc) | (parity & 0x03));
return tmpstr;
}
public static String btoe(int index) {
if (index < words.length) {
return words[index];
} else {
return "bogus";
}
}
static String words[] =
{ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
"AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY",
"AN", "ANA", "AND", "ANN", "ANT", "ANY", "APE", "APS",
"APT", "ARC", "ARE", "ARK", "ARM", "ART", "AS", "ASH",
"ASK", "AT", "ATE", "AUG", "AUK", "AVE", "AWE", "AWK",
"AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
"BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG",
"BEN", "BET", "BEY", "BIB", "BID", "BIG", "BIN", "BIT",
"BOB", "BOG", "BON", "BOO", "BOP", "BOW", "BOY", "BUB",
"BUD", "BUG", "BUM", "BUN", "BUS", "BUT", "BUY", "BY",
"BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
"CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT",
"COW", "COY", "CRY", "CUB", "CUE", "CUP", "CUR", "CUT",
"DAB", "DAD", "DAM", "DAN", "DAR", "DAY", "DEE", "DEL",
"DEN", "DES", "DEW", "DID", "DIE", "DIG", "DIN", "DIP",
"DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
"DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL",
"EGG", "EGO", "ELI", "ELK", "ELM", "ELY", "EM", "END",
"EST", "ETC", "EVA", "EVE", "EWE", "EYE", "FAD", "FAN",
"FAR", "FAT", "FAY", "FED", "FEE", "FEW", "FIB", "FIG",
"FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
"FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL",
"GAM", "GAP", "GAS", "GAY", "GEE", "GEL", "GEM", "GET",
"GIG", "GIL", "GIN", "GO", "GOT", "GUM", "GUN", "GUS",
"GUT", "GUY", "GYM", "GYP", "HA", "HAD", "HAL", "HAM",
"HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
"HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP",
"HIS", "HIT", "HO", "HOB", "HOC", "HOE", "HOG", "HOP",
"HOT", "HOW", "HUB", "HUE", "HUG", "HUH", "HUM", "HUT",
"I", "ICY", "IDA", "IF", "IKE", "ILL", "INK", "INN",
"IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT",
"ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW",
"JAY", "JET", "JIG", "JIM", "JO", "JOB", "JOE", "JOG",
"JOT", "JOY", "JUG", "JUT", "KAY", "KEG", "KEN", "KEY",
"KID", "KIM", "KIN", "KIT", "LA", "LAB", "LAC", "LAD",
"LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE",
"LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN",
"LIP", "LIT", "LO", "LOB", "LOG", "LOP", "LOS", "LOT",
"LOU", "LOW", "LOY", "LUG", "LYE", "MA", "MAC", "MAD",
"MAE", "MAN", "MAO", "MAP", "MAT", "MAW", "MAY", "ME",
"MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT",
"MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW",
"MUD", "MUG", "MUM", "MY", "NAB", "NAG", "NAN", "NAP",
"NAT", "NAY", "NE", "NED", "NEE", "NET", "NEW", "NIB",
"NIL", "NIP", "NIT", "NO", "NOB", "NOD", "NON", "NOR",
"NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF",
"OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT",
"OH", "OIL", "OK", "OLD", "ON", "ONE", "OR", "ORB",
"ORE", "ORR", "OS", "OTT", "OUR", "OUT", "OVA", "OW",
"OWE", "OWL", "OWN", "OX", "PA", "PAD", "PAL", "PAM",
"PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG",
"PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE",
"PIN", "PIT", "PLY", "PO", "POD", "POE", "POP", "POT",
"POW", "PRO", "PRY", "PUB", "PUG", "PUN", "PUP", "PUT",
"QUO", "RAG", "RAM", "RAN", "RAP", "RAT", "RAW", "RAY",
"REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM",
"RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW",
"ROY", "RUB", "RUE", "RUG", "RUM", "RUN", "RYE", "SAC",
"SAD", "SAG", "SAL", "SAM", "SAN", "SAP", "SAT", "SAW",
"SAY", "SEA", "SEC", "SEE", "SEN", "SET", "SEW", "SHE",
"SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY",
"SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY",
"SPA", "SPY", "SUB", "SUD", "SUE", "SUM", "SUN", "SUP",
"TAB", "TAD", "TAG", "TAN", "TAP", "TAR", "TEA", "TED",
"TEE", "TEN", "THE", "THY", "TIC", "TIE", "TIM", "TIN",
"TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP",
"TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO",
"UN", "UP", "US", "USE", "VAN", "VAT", "VET", "VIE",
"WAD", "WAG", "WAR", "WAS", "WAY", "WE", "WEB", "WED",
"WEE", "WET", "WHO", "WHY", "WIN", "WIT", "WOK", "WON",
"WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE",
"YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE",
"ABUT", "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM",
"ADDS", "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA",
"AIDE", "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA",
"ALIA", "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA",
"AMEN", "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY",
"ANEW", "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH",
"AREA", "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS",
"ATOM", "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON",
"AVOW", "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE",
"BAIL", "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL",
"BALM", "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE",
"BARK", "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE",
"BATH", "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR",
"BEAT", "BEAU", "BECK", "BEEF", "BEEN", "BEER", "BEET", "BELA",
"BELL", "BELT", "BEND", "BENT", "BERG", "BERN", "BERT", "BESS",
"BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE", "BIEN", "BILE",
"BILK", "BILL", "BIND", "BING", "BIRD", "BITE", "BITS", "BLAB",
"BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT", "BLOW", "BLUE",
"BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK", "BODE",
|