diff options
Diffstat (limited to 'tcllib/modules/otp')
-rw-r--r-- | tcllib/modules/otp/ChangeLog | 59 | ||||
-rw-r--r-- | tcllib/modules/otp/otp.man | 95 | ||||
-rw-r--r-- | tcllib/modules/otp/otp.tcl | 430 | ||||
-rw-r--r-- | tcllib/modules/otp/otp.test | 146 | ||||
-rw-r--r-- | tcllib/modules/otp/pkgIndex.tcl | 3 |
5 files changed, 733 insertions, 0 deletions
diff --git a/tcllib/modules/otp/ChangeLog b/tcllib/modules/otp/ChangeLog new file mode 100644 index 0000000..c6ecb57 --- /dev/null +++ b/tcllib/modules/otp/ChangeLog @@ -0,0 +1,59 @@ +2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.15 ======================== + * + +2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.14 ======================== + * + +2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.13 ======================== + * + +2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.12 ======================== + * + +2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11.1 ======================== + * + +2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.11 ======================== + * + +2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.10 ======================== + * + +2007-03-21 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * otp.man: Fixed all warnings due to use of now deprecated + commands. Added a section about how to give feedback. + +2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net> + + * + * Released and tagged Tcllib 1.9 ======================== + * + +2006-09-01 Pat Thoyts <patthoyts@users.sourceforge.net> + + * modules/otp/otp.tcl: Initial version of RFC 2289 implementation + * modules/otp/otp.test: "A One-Time Password System" + * modules/otp/otp.man: + diff --git a/tcllib/modules/otp/otp.man b/tcllib/modules/otp/otp.man new file mode 100644 index 0000000..cbc9ff4 --- /dev/null +++ b/tcllib/modules/otp/otp.man @@ -0,0 +1,95 @@ +[manpage_begin otp n 1.0.0] +[see_also md4] +[see_also md5] +[see_also ripemd160] +[see_also SASL] +[see_also sha1] +[keywords hashing] +[keywords message-digest] +[keywords password] +[keywords {rfc 2289}] +[keywords security] +[moddesc {RFC 2289 A One-Time Password System}] +[copyright {2006, Pat Thoyts <patthoyts@users.sourceforge.net>}] +[titledesc {One-Time Passwords}] +[category {Hashes, checksums, and encryption}] +[require Tcl 8.2] +[require otp [opt 1.0.0]] +[description] +[para] + +This package is an implementation in Tcl of the One-Time Password +system as described in RFC 2289 (1). This system uses message-digest +algorithms to sequentially hash a passphrase to create single-use +passwords. The resulting data is then provided to the user as either +hexadecimal digits or encoded using a dictionary of 2048 words. This +system is used by OpenBSD for secure login and can be used as a SASL +mechanism for authenticating users. + +[para] + +In this implementation we provide support for four algorithms that are +included in the tcllib distribution: MD5 (2), MD4 (3), RIPE-MD160 (4) +and SHA-1 (5). + +[section {COMMANDS}] + +[list_begin definitions] + +[call [cmd "::otp::otp-md4"] [opt "[arg -hex]"] [opt "[arg -words]"] \ + [arg "-seed seed"] [arg "-count count"] [arg "data"]] + +[call [cmd "::otp::otp-md5"] [opt "[arg -hex]"] [opt "[arg -words]"] \ + [arg "-seed seed"] [arg "-count count"] [arg "data"]] + +[call [cmd "::otp::otp-sha1"] [opt "[arg -hex]"] [opt "[arg -words]"] \ + [arg "-seed seed"] [arg "-count count"] [arg "data"]] + +[call [cmd "::otp::otp-rmd160"] [opt "[arg -hex]"] [opt "[arg -words]"] \ + [arg "-seed seed"] [arg "-count count"] [arg "data"]] + +[list_end] + +[section {EXAMPLES}] + +[example { +% otp::otp-md5 -count 99 -seed host67821 "My Secret Pass Phrase" +(binary gibberish) +% otp::otp-md5 -words -count 99 -seed host67821 "My Secret Pass Phrase" +SOON ARAB BURG LIMB FILE WAD +% otp::otp-md5 -hex -count 99 -seed host67821 "My Secret Pass Phrase" +e249b58257c80087 +}] + +[section {REFERENCES}] + +[list_begin enumerated] + +[enum] + Haller, N. et al., "A One-Time Password System", RFC 2289, February 1998. + [uri http://www.rfc-editor.org/rfc/rfc2289.txt] + +[enum] + Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, MIT and + RSA Data Security, Inc, April 1992. + ([uri http://www.rfc-editor.org/rfc/rfc1321.txt]) + +[enum] + Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT, + April 1992. ([uri http://www.rfc-editor.org/rfc/rfc1320.txt]) + +[enum] + H. Dobbertin, A. Bosselaers, B. Preneel, + "RIPEMD-160, a strengthened version of RIPEMD" + [uri http://www.esat.kuleuven.ac.be/~cosicart/pdf/AB-9601/AB-9601.pdf] + +[enum] + "Secure Hash Standard", National Institute of Standards + and Technology, U.S. Department Of Commerce, April 1995. + ([uri http://www.itl.nist.gov/fipspubs/fip180-1.htm]) + +[list_end] + +[vset CATEGORY otp] +[include ../doctools2base/include/feedback.inc] +[manpage_end] diff --git a/tcllib/modules/otp/otp.tcl b/tcllib/modules/otp/otp.tcl new file mode 100644 index 0000000..dede029 --- /dev/null +++ b/tcllib/modules/otp/otp.tcl @@ -0,0 +1,430 @@ +# otp.tcl - Copyright (C) 2006 Pat Thoyts <patthoyts@users.sourceforge.net> +# +# Tcl implementation of RFC 2289: A One-Time Password System +# +# ------------------------------------------------------------------------- +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# ------------------------------------------------------------------------- + + +package require Tcl 8.2; # tcl minimum version + +namespace eval ::otp { + namespace export otp-md4 otp-md5 otp-sha1 otp-rmd160 + + variable 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" "BODY" + "BOGY" "BOHR" "BOIL" "BOLD" "BOLO" "BOLT" "BOMB" "BONA" + "BOND" "BONE" "BONG" "BONN" "BONY" "BOOK" "BOOM" "BOON" + "BOOT" "BORE" "BORG" "BORN" "BOSE" "BOSS" "BOTH" "BOUT" + "BOWL" "BOYD" "BRAD" "BRAE" "BRAG" "BRAN" "BRAY" "BRED" + "BREW" "BRIG" "BRIM" "BROW" "BUCK" "BUDD" "BUFF" "BULB" + "BULK" "BULL" "BUNK" "BUNT" "BUOY" "BURG" "BURL" "BURN" + "BURR" "BURT" "BURY" "BUSH" "BUSS" "BUST" "BUSY" "BYTE" + "CADY" "CAFE" "CAGE" "CAIN" "CAKE" "CALF" "CALL" "CALM" + "CAME" "CANE" "CANT" "CARD" "CARE" "CARL" "CARR" "CART" + "CASE" "CASH" "CASK" "CAST" "CAVE" "CEIL" "CELL" "CENT" + "CERN" "CHAD" "CHAR" "CHAT" "CHAW" "CHEF" "CHEN" "CHEW" + "CHIC" "CHIN" "CHOU" "CHOW" "CHUB" "CHUG" "CHUM" "CITE" + "CITY" "CLAD" "CLAM" "CLAN" "CLAW" "CLAY" "CLOD" "CLOG" + "CLOT" "CLUB" "CLUE" "COAL" "COAT" "COCA" "COCK" "COCO" + "CODA" "CODE" "CODY" "COED" "COIL" "COIN" "COKE" "COLA" + "COLD" "COLT" "COMA" "COMB" "COME" "COOK" "COOL" "COON" + "COOT" "CORD" "CORE" "CORK" "CORN" "COST" "COVE" "COWL" + "CRAB" "CRAG" "CRAM" "CRAY" "CREW" "CRIB" "CROW" "CRUD" + "CUBA" "CUBE" "CUFF" "CULL" "CULT" "CUNY" "CURB" "CURD" + "CURE" "CURL" "CURT" "CUTS" "DADE" "DALE" "DAME" "DANA" + "DANE" "DANG" "DANK" "DARE" "DARK" "DARN" "DART" "DASH" + "DATA" "DATE" "DAVE" "DAVY" "DAWN" "DAYS" "DEAD" "DEAF" + "DEAL" "DEAN" "DEAR" "DEBT" "DECK" "DEED" "DEEM" "DEER" + "DEFT" "DEFY" "DELL" "DENT" "DENY" "DESK" "DIAL" "DICE" + "DIED" "DIET" "DIME" "DINE" "DING" "DINT" "DIRE" "DIRT" + "DISC" "DISH" "DISK" "DIVE" "DOCK" "DOES" "DOLE" "DOLL" + "DOLT" "DOME" "DONE" "DOOM" "DOOR" "DORA" "DOSE" "DOTE" + "DOUG" "DOUR" "DOVE" "DOWN" "DRAB" "DRAG" "DRAM" "DRAW" + "DREW" "DRUB" "DRUG" "DRUM" "DUAL" "DUCK" "DUCT" "DUEL" + "DUET" "DUKE" "DULL" "DUMB" "DUNE" "DUNK" "DUSK" "DUST" + "DUTY" "EACH" "EARL" "EARN" "EASE" "EAST" "EASY" "EBEN" + "ECHO" "EDDY" "EDEN" "EDGE" "EDGY" "EDIT" "EDNA" "EGAN" + "ELAN" "ELBA" "ELLA" "ELSE" "EMIL" "EMIT" "EMMA" "ENDS" + "ERIC" "EROS" "EVEN" "EVER" "EVIL" "EYED" "FACE" "FACT" + "FADE" "FAIL" "FAIN" "FAIR" "FAKE" "FALL" "FAME" "FANG" + "FARM" "FAST" "FATE" "FAWN" "FEAR" "FEAT" "FEED" "FEEL" + "FEET" "FELL" "FELT" "FEND" "FERN" "FEST" "FEUD" "FIEF" + "FIGS" "FILE" "FILL" "FILM" "FIND" "FINE" "FINK" "FIRE" + "FIRM" "FISH" "FISK" "FIST" "FITS" "FIVE" "FLAG" "FLAK" + "FLAM" "FLAT" "FLAW" "FLEA" "FLED" "FLEW" "FLIT" "FLOC" + "FLOG" "FLOW" "FLUB" "FLUE" "FOAL" "FOAM" "FOGY" "FOIL" + "FOLD" "FOLK" "FOND" "FONT" "FOOD" "FOOL" "FOOT" "FORD" + "FORE" "FORK" "FORM" "FORT" "FOSS" "FOUL" "FOUR" "FOWL" + "FRAU" "FRAY" "FRED" "FREE" "FRET" "FREY" "FROG" "FROM" + "FUEL" "FULL" "FUME" "FUND" "FUNK" "FURY" "FUSE" "FUSS" + "GAFF" "GAGE" "GAIL" "GAIN" "GAIT" "GALA" "GALE" "GALL" + "GALT" "GAME" "GANG" "GARB" "GARY" "GASH" "GATE" "GAUL" + "GAUR" "GAVE" "GAWK" "GEAR" "GELD" "GENE" "GENT" "GERM" + "GETS" "GIBE" "GIFT" "GILD" "GILL" "GILT" "GINA" "GIRD" + "GIRL" "GIST" "GIVE" "GLAD" "GLEE" "GLEN" "GLIB" "GLOB" + "GLOM" "GLOW" "GLUE" "GLUM" "GLUT" "GOAD" "GOAL" "GOAT" + "GOER" "GOES" "GOLD" "GOLF" "GONE" "GONG" "GOOD" "GOOF" + "GORE" "GORY" "GOSH" "GOUT" "GOWN" "GRAB" "GRAD" "GRAY" + "GREG" "GREW" "GREY" "GRID" "GRIM" "GRIN" "GRIT" "GROW" + "GRUB" "GULF" "GULL" "GUNK" "GURU" "GUSH" "GUST" "GWEN" + "GWYN" "HAAG" "HAAS" "HACK" "HAIL" "HAIR" "HALE" "HALF" + "HALL" "HALO" "HALT" "HAND" "HANG" "HANK" "HANS" "HARD" + "HARK" "HARM" "HART" "HASH" "HAST" "HATE" "HATH" "HAUL" + "HAVE" "HAWK" "HAYS" "HEAD" "HEAL" "HEAR" "HEAT" "HEBE" + "HECK" "HEED" "HEEL" "HEFT" "HELD" "HELL" "HELM" "HERB" + "HERD" "HERE" "HERO" "HERS" "HESS" "HEWN" "HICK" "HIDE" + "HIGH" "HIKE" "HILL" "HILT" "HIND" "HINT" "HIRE" "HISS" + "HIVE" "HOBO" "HOCK" "HOFF" "HOLD" "HOLE" "HOLM" "HOLT" + "HOME" "HONE" "HONK" "HOOD" "HOOF" "HOOK" "HOOT" "HORN" + "HOSE" "HOST" "HOUR" "HOVE" "HOWE" "HOWL" "HOYT" "HUCK" + "HUED" "HUFF" "HUGE" "HUGH" "HUGO" "HULK" "HULL" "HUNK" + "HUNT" "HURD" "HURL" "HURT" "HUSH" "HYDE" "HYMN" "IBIS" + "ICON" "IDEA" "IDLE" "IFFY" "INCA" "INCH" "INTO" "IONS" + "IOTA" "IOWA" "IRIS" "IRMA" "IRON" "ISLE" "ITCH" "ITEM" + "IVAN" "JACK" "JADE" "JAIL" "JAKE" "JANE" "JAVA" "JEAN" + "JEFF" "JERK" "JESS" "JEST" "JIBE" "JILL" "JILT" "JIVE" + "JOAN" "JOBS" "JOCK" "JOEL" "JOEY" "JOHN" "JOIN" "JOKE" + "JOLT" "JOVE" "JUDD" "JUDE" "JUDO" "JUDY" "JUJU" "JUKE" + "JULY" "JUNE" "JUNK" "JUNO" "JURY" "JUST" "JUTE" "KAHN" + "KALE" "KANE" "KANT" "KARL" "KATE" "KEEL" "KEEN" "KENO" + "KENT" "KERN" "KERR" "KEYS" "KICK" "KILL" "KIND" "KING" + "KIRK" "KISS" "KITE" "KLAN" "KNEE" "KNEW" "KNIT" "KNOB" + "KNOT" "KNOW" "KOCH" "KONG" "KUDO" "KURD" "KURT" "KYLE" + "LACE" "LACK" "LACY" "LADY" "LAID" "LAIN" "LAIR" "LAKE" + "LAMB" "LAME" "LAND" "LANE" "LANG" "LARD" "LARK" "LASS" + "LAST" "LATE" "LAUD" "LAVA" "LAWN" "LAWS" "LAYS" "LEAD" + "LEAF" "LEAK" "LEAN" "LEAR" "LEEK" "LEER" "LEFT" "LEND" + "LENS" "LENT" "LEON" "LESK" "LESS" "LEST" "LETS" "LIAR" + "LICE" "LICK" "LIED" "LIEN" "LIES" "LIEU" "LIFE" "LIFT" + "LIKE" "LILA" "LILT" "LILY" "LIMA" "LIMB" "LIME" "LIND" + "LINE" "LINK" "LINT" "LION" "LISA" "LIST" "LIVE" "LOAD" + "LOAF" "LOAM" "LOAN" "LOCK" "LOFT" "LOGE" "LOIS" "LOLA" + "LONE" "LONG" "LOOK" "LOON" "LOOT" "LORD" "LORE" "LOSE" + "LOSS" "LOST" "LOUD" "LOVE" "LOWE" "LUCK" "LUCY" "LUGE" + "LUKE" "LULU" "LUND" "LUNG" "LURA" "LURE" "LURK" "LUSH" + "LUST" "LYLE" "LYNN" "LYON" "LYRA" "MACE" "MADE" "MAGI" + "MAID" "MAIL" "MAIN" "MAKE" "MALE" "MALI" "MALL" "MALT" + "MANA" "MANN" "MANY" "MARC" "MARE" "MARK" "MARS" "MART" + "MARY" "MASH" "MASK" "MASS" "MAST" "MATE" "MATH" "MAUL" + "MAYO" "MEAD" "MEAL" "MEAN" "MEAT" "MEEK" "MEET" "MELD" + "MELT" "MEMO" "MEND" "MENU" "MERT" "MESH" "MESS" "MICE" + "MIKE" "MILD" "MILE" "MILK" "MILL" "MILT" "MIMI" "MIND" + "MINE" "MINI" "MINK" "MINT" "MIRE" "MISS" "MIST" "MITE" + "MITT" "MOAN" "MOAT" "MOCK" "MODE" "MOLD" "MOLE" "MOLL" + "MOLT" "MONA" "MONK" "MONT" "MOOD" "MOON" "MOOR" "MOOT" + "MORE" "MORN" "MORT" "MOSS" "MOST" "MOTH" "MOVE" "MUCH" + "MUCK" "MUDD" "MUFF" "MULE" "MULL" "MURK" "MUSH" "MUST" + "MUTE" "MUTT" "MYRA" "MYTH" "NAGY" "NAIL" "NAIR" "NAME" + "NARY" "NASH" "NAVE" "NAVY" "NEAL" "NEAR" "NEAT" "NECK" + "NEED" "NEIL" "NELL" "NEON" "NERO" "NESS" "NEST" "NEWS" + "NEWT" "NIBS" "NICE" "NICK" "NILE" "NINA" "NINE" "NOAH" + "NODE" "NOEL" "NOLL" "NONE" "NOOK" "NOON" "NORM" "NOSE" + "NOTE" "NOUN" "NOVA" "NUDE" "NULL" "NUMB" "OATH" "OBEY" + "OBOE" "ODIN" "OHIO" "OILY" "OINT" "OKAY" "OLAF" "OLDY" + "OLGA" "OLIN" "OMAN" "OMEN" "OMIT" "ONCE" "ONES" "ONLY" + "ONTO" "ONUS" "ORAL" "ORGY" "OSLO" "OTIS" "OTTO" "OUCH" + "OUST" "OUTS" "OVAL" "OVEN" "OVER" "OWLY" "OWNS" "QUAD" + "QUIT" "QUOD" "RACE" "RACK" "RACY" "RAFT" "RAGE" "RAID" + "RAIL" "RAIN" "RAKE" "RANK" "RANT" "RARE" "RASH" "RATE" + "RAVE" "RAYS" "READ" "REAL" "REAM" "REAR" "RECK" "REED" + "REEF" "REEK" "REEL" "REID" "REIN" "RENA" "REND" "RENT" + "REST" "RICE" "RICH" "RICK" "RIDE" "RIFT" "RILL" "RIME" + "RING" "RINK" "RISE" "RISK" "RITE" "ROAD" "ROAM" "ROAR" + "ROBE" "ROCK" "RODE" "ROIL" "ROLL" "ROME" "ROOD" "ROOF" + "ROOK" "ROOM" "ROOT" "ROSA" "ROSE" "ROSS" "ROSY" "ROTH" + "ROUT" "ROVE" "ROWE" "ROWS" "RUBE" "RUBY" "RUDE" "RUDY" + "RUIN" "RULE" "RUNG" "RUNS" "RUNT" "RUSE" "RUSH" "RUSK" + "RUSS" "RUST" "RUTH" "SACK" "SAFE" "SAGE" "SAID" "SAIL" + "SALE" "SALK" "SALT" "SAME" "SAND" "SANE" "SANG" "SANK" + "SARA" "SAUL" "SAVE" "SAYS" "SCAN" "SCAR" "SCAT" "SCOT" + "SEAL" "SEAM" "SEAR" "SEAT" "SEED" "SEEK" "SEEM" "SEEN" + "SEES" "SELF" "SELL" "SEND" "SENT" "SETS" "SEWN" "SHAG" + "SHAM" "SHAW" "SHAY" "SHED" "SHIM" "SHIN" "SHOD" "SHOE" + "SHOT" "SHOW" "SHUN" "SHUT" "SICK" "SIDE" "SIFT" "SIGH" + "SIGN" "SILK" "SILL" "SILO" "SILT" "SINE" "SING" "SINK" + "SIRE" "SITE" "SITS" "SITU" "SKAT" "SKEW" "SKID" "SKIM" + "SKIN" "SKIT" "SLAB" "SLAM" "SLAT" "SLAY" "SLED" "SLEW" + "SLID" "SLIM" "SLIT" "SLOB" "SLOG" "SLOT" "SLOW" "SLUG" + "SLUM" "SLUR" "SMOG" "SMUG" "SNAG" "SNOB" "SNOW" "SNUB" + "SNUG" "SOAK" "SOAR" "SOCK" "SODA" "SOFA" "SOFT" "SOIL" + "SOLD" "SOME" "SONG" "SOON" "SOOT" "SORE" "SORT" "SOUL" + "SOUR" "SOWN" "STAB" "STAG" "STAN" "STAR" "STAY" "STEM" + "STEW" "STIR" "STOW" "STUB" "STUN" "SUCH" "SUDS" "SUIT" + "SULK" "SUMS" "SUNG" "SUNK" "SURE" "SURF" "SWAB" "SWAG" + "SWAM" "SWAN" "SWAT" "SWAY" "SWIM" "SWUM" "TACK" "TACT" + "TAIL" "TAKE" "TALE" "TALK" "TALL" "TANK" "TASK" "TATE" + "TAUT" "TEAL" "TEAM" "TEAR" "TECH" "TEEM" "TEEN" "TEET" + "TELL" "TEND" "TENT" "TERM" "TERN" "TESS" "TEST" "THAN" + "THAT" "THEE" "THEM" "THEN" "THEY" "THIN" "THIS" "THUD" + "THUG" "TICK" "TIDE" "TIDY" "TIED" "TIER" "TILE" "TILL" + "TILT" "TIME" "TINA" "TINE" "TINT" "TINY" "TIRE" "TOAD" + "TOGO" "TOIL" "TOLD" "TOLL" "TONE" "TONG" "TONY" "TOOK" + "TOOL" "TOOT" "TORE" "TORN" "TOTE" "TOUR" "TOUT" "TOWN" + "TRAG" "TRAM" "TRAY" "TREE" "TREK" "TRIG" "TRIM" "TRIO" + "TROD" "TROT" "TROY" "TRUE" "TUBA" "TUBE" "TUCK" "TUFT" + "TUNA" "TUNE" "TUNG" "TURF" "TURN" "TUSK" "TWIG" "TWIN" + "TWIT" "ULAN" "UNIT" "URGE" "USED" "USER" "USES" "UTAH" + "VAIL" "VAIN" "VALE" "VARY" "VASE" "VAST" "VEAL" "VEDA" + "VEIL" "VEIN" "VEND" "VENT" "VERB" "VERY" "VETO" "VICE" + "VIEW" "VINE" "VISE" "VOID" "VOLT" "VOTE" "WACK" "WADE" + "WAGE" "WAIL" "WAIT" "WAKE" "WALE" "WALK" "WALL" "WALT" + "WAND" "WANE" "WANG" "WANT" "WARD" "WARM" "WARN" "WART" + "WASH" "WAST" "WATS" "WATT" "WAVE" "WAVY" "WAYS" "WEAK" + "WEAL" "WEAN" "WEAR" "WEED" "WEEK" "WEIR" "WELD" "WELL" + "WELT" "WENT" "WERE" "WERT" "WEST" "WHAM" "WHAT" "WHEE" + "WHEN" "WHET" "WHOA" "WHOM" "WICK" "WIFE" "WILD" "WILL" + "WIND" "WINE" "WING" "WINK" "WINO" "WIRE" "WISE" "WISH" + "WITH" "WOLF" "WONT" "WOOD" "WOOL" "WORD" "WORE" "WORK" + "WORM" "WORN" "WOVE" "WRIT" "WYNN" "YALE" "YANG" "YANK" + "YARD" "YARN" "YAWL" "YAWN" "YEAH" "YEAR" "YELL" "YOGA" + "YOKE" + } +} + +# Encode 64 bits as words selected from the RFC 2289 dictionary. +# See the RFC for details. Briefly the input is broken into 11 bit +# chunks + 2bits of checksum and each chunk selects a word from the +# 2048 word table. +# +proc ::otp::otp_encode {data} { + variable Words + if {[string length $data] != 8} { + set bc [expr {[string length $data] * 8}] + return -code error "invalid input: 64 bits of data\ + required and $bc bits provided" + } + binary scan $data II A B + + set cksum 0 + foreach w [list $A $B] { + for {set n 0} {$n < 32} {incr n 2} { + incr cksum [expr {($w >> $n) & 3}] + } + } + + set W0 [expr { (($A & 0xFFE00000) >> 21) & 0x07ff}] + set W1 [expr { (($A & 0x001FFC00) >> 10)}] + set W2 [expr { (($A & 0x000003FF) << 1) | (($B >> 31) & 0x1)}] + set W3 [expr { ($B & 0x7FF00000) >> 20}] + set W4 [expr { ($B & 0x000FFE00) >> 9}] + set W5 [expr { (($B & 0x000001FF) << 2) | ($cksum & 3)}] + + foreach w [list $W0 $W1 $W2 $W3 $W4 $W5] { + lappend words [lindex $Words $w] + } + + return $words +} + +# Fold a 128 bit digest in little-endian format into a 64 bit +# little-endian output +proc ::otp::Fold64LE {digest} { + binary scan $digest iiii A B C D + set w0 [expr {($A ^ $C) & 0xffffffff}] + set w1 [expr {($B ^ $D) & 0xffffffff}] + binary format ii $w0 $w1 +} + +# Fold a160 bit big-endian digest (SHA-1) into a 64 bit +# little-endian output +proc ::otp::Fold160BE {digest} { + binary scan $digest IIIII A B C D E + set w0 [expr {(($A ^ $C) ^ $E) & 0xffffffff}] + set w1 [expr { ($B ^ $D) & 0xffffffff}] + binary format ii $w0 $w1 +} + +# Fold a 160 bit little-endian digest into a 64 bit +# little-endian output. +proc ::otp::Fold160LE {digest} { + binary scan $digest iiiii A B C D E + set w0 [expr {(($A ^ $C) ^ $E) & 0xffffffff}] + set w1 [expr { ($B ^ $D) & 0xffffffff}] + binary format ii $w0 $w1 +} + +# Description: +# Pop the nth element off a list. Used in options processing. +# +proc ::otp::Pop {varname {nth 0}} { + upvar $varname args + set r [lindex $args $nth] + set args [lreplace $args $nth $nth] + return $r +} + +proc ::otp::otp {args} { + array set opts {-hash md5 -seed {} -count 0 -hex 0 -words 0} + while {[string match -* [set option [lindex $args 0]]]} { + switch -exact -- $option { + -hex { set opts(-hex) 1} + -word - + -words { set opts(-words) 1 } + -hash { set opts(-hash) [Pop args 1] } + -seed { set opts(-seed) [Pop args 1] } + -count { set opts(-count) [Pop args 1] } + default { + if {[llength $args] == 1} { break } + if {[string compare $option "--"] == 0} { Pop args; break } + set err [join [lsort [array names opts]] ", "] + return -code error "bad option \"$option\":\ + must be one of $err" + } + } + Pop args + } + + set data [lindex $args 0] + + if {[string length $opts(-seed)] < 1 || [string length $opts(-seed)] > 16} { + return -code error "seed must be between 1 and 16 characters in length" + } + switch -exact -- $opts(-hash) { + md4 { set func ::md4::md4 ; set fold ::otp::Fold64LE } + md5 { set func ::md5::md5 ; set fold ::otp::Fold64LE } + sha1 { set func ::otp::sha1 ; set fold ::otp::Fold160BE } + rmd160 { set func ::ripemd::ripemd160 ; set fold ::otp::Fold160LE } + default { + return -code error "invalid hash type \"$opts(-hash)\":\ + must be one of md4, md5, rmd160 or sha1" + } + } + # RFC 2289: Initial step + set S [$fold [$func [string tolower $opts(-seed)]$data]] + + # RFC2289:6 Computation step + for {set n 0} {$n < $opts(-count)} {incr n} { + set S [$fold [$func $S]] + } + + if {$opts(-hex)} { + binary scan $S H* S + } elseif {$opts(-words)} { + set S [otp_encode $S] + } + return $S +} + +proc ::otp::otp-md4 {args} { + package require md4 + return [eval [linsert $args 0 [namespace current]::otp -hash md4]] +} + +proc ::otp::otp-md5 {args} { + package require md5 + return [eval [linsert $args 0 [namespace current]::otp -hash md5]] +} + +proc ::otp::otp-sha1 {args} { + package require sha1 + interp alias {} ::otp::sha1 {} ::sha1::sha1 -bin + return [eval [linsert $args 0 [namespace current]::otp -hash sha1]] +} + +proc ::otp::otp-rmd160 {args} { + package require ripemd160 + return [eval [linsert $args 0 [namespace current]::otp -hash rmd160]] +} + +# ------------------------------------------------------------------------- + +package provide otp 1.0.0 + +# ------------------------------------------------------------------------- +# Local Variables: +# mode: tcl +# indent-tabs-mode: nil +# End: diff --git a/tcllib/modules/otp/otp.test b/tcllib/modules/otp/otp.test new file mode 100644 index 0000000..83d3ff2 --- /dev/null +++ b/tcllib/modules/otp/otp.test @@ -0,0 +1,146 @@ +# -*- tcl -*- +# otp.test: tests the OTP implementation. Most of the tests are directly +# copied from RFC 2289. +# +# This file contains a collection of tests for one or more of the Tcl +# built-in commands. Sourcing this file into Tcl runs the tests and +# generates output for errors. No output means no errors were found. +# +# Copyright (c) 2006 Patrick Thoyts +# +# RCS: @(#) $Id: otp.test,v 1.2 2006/10/09 21:41:41 andreas_kupries Exp $ + +# ------------------------------------------------------------------------- + +source [file join \ + [file dirname [file dirname [file join [pwd] [info script]]]] \ + devtools testutilities.tcl] + +testsNeedTcl 8.2 +testsNeedTcltest 1.0 + +testing { + useLocal otp.tcl otp +} + +# ------------------------------------------------------------------------- + +set tests_md5 { + 0 "This is a test." "TeSt" 0 "9E876134D90499DD" "INCH SEA ANNE LONG AHEM TOUR" + 1 "This is a test." "TeSt" 1 "7965E05436F5029F" "EASE OIL FUM CURE AWRY AVIS" + 2 "This is a test." "TeSt" 99 "50FE1962C4965880" "BAIL TUFT BITS GANG CHEF THY" + 3 "AbCdEfGhIjK" "alpha1" 0 "87066DD9644BF206" "FULL PEW DOWN ONCE MORT ARC" + 4 "AbCdEfGhIjK" "alpha1" 1 "7CD34C1040ADD14B" "FACT HOOF AT FIST SITE KENT" + 5 "AbCdEfGhIjK" "alpha1" 99 "5AA37A81F212146C" "BODE HOP JAKE STOW JUT RAP" + 6 "OTP's are good" "correct" 0 "F205753943DE4CF9" "ULAN NEW ARMY FUSE SUIT EYED" + 7 "OTP's are good" "correct" 1 "DDCDAC956F234937" "SKIM CULT LOB SLAM POE HOWL" + 8 "OTP's are good" "correct" 99 "B203E28FA525BE47" "LONG IVY JULY AJAR BOND LEE" +} + +foreach {ndx pass seed cnt hex wrds} $tests_md5 { + test otp-md5-hex-$ndx "otp-md5 check hex result" { + list [catch { + set res [::otp::otp-md5 -hex -seed $seed -count $cnt $pass] + string toupper $res + } msg] $msg + } [list 0 $hex] +} + +foreach {ndx pass seed cnt hex wrds} $tests_md5 { + test otp-md5-words-$ndx "otp-md5 check words encoding" { + list [catch { + set res [::otp::otp-md5 -words -seed $seed -count $cnt $pass] + } msg] $msg + } [list 0 $wrds] +} + + +set tests_md4 { + 0 "This is a test." "TeSt" 0 "D1854218EBBB0B51" "ROME MUG FRED SCAN LIVE LACE" + 1 "This is a test." "TeSt" 1 "63473EF01CD0B444" "CARD SAD MINI RYE COL KIN" + 2 "This is a test." "TeSt" 99 "C5E612776E6C237A" "NOTE OUT IBIS SINK NAVE MODE" + 3 "AbCdEfGhIjK" "alpha1" 0 "50076F47EB1ADE4E" "AWAY SEN ROOK SALT LICE MAP" + 4 "AbCdEfGhIjK" "alpha1" 1 "65D20D1949B5F7AB" "CHEW GRIM WU HANG BUCK SAID" + 5 "AbCdEfGhIjK" "alpha1" 99 "D150C82CCE6F62D1" "ROIL FREE COG HUNK WAIT COCA" + 6 "OTP's are good" "correct" 0 "849C79D4F6F55388" "FOOL STEM DONE TOOL BECK NILE" + 7 "OTP's are good" "correct" 1 "8C0992FB250847B1" "GIST AMOS MOOT AIDS FOOD SEEM" + 8 "OTP's are good" "correct" 99 "3F3BF4B4145FD74B" "TAG SLOW NOV MIN WOOL KENO" +} + +foreach {ndx pass seed cnt hex wrds} $tests_md4 { + test otp-md4-hex-$ndx "otp-md4 check hex result" { + list [catch { + set res [::otp::otp-md4 -hex -seed $seed -count $cnt $pass] + string toupper $res + } msg] $msg + } [list 0 $hex] +} + +foreach {ndx pass seed cnt hex wrds} $tests_md4 { + test otp-md4-words-$ndx "otp-md4 check words encoding" { + list [catch { + set res [::otp::otp-md4 -words -seed $seed -count $cnt $pass] + } msg] $msg + } [list 0 $wrds] +} + +set tests_sha1 { + 0 "This is a test." "TeSt" 0 "BB9E6AE1979D8FF4" "MILT VARY MAST OK SEES WENT" + 1 "This is a test." "TeSt" 1 "63D936639734385B" "CART OTTO HIVE ODE VAT NUT" + 2 "This is a test." "TeSt" 99 "87FEC7768B73CCF9" "GAFF WAIT SKID GIG SKY EYED" + 3 "AbCdEfGhIjK" "alpha1" 0 "AD85F658EBE383C9" "LEST OR HEEL SCOT ROB SUIT" + 4 "AbCdEfGhIjK" "alpha1" 1 "D07CE229B5CF119B" "RITE TAKE GELD COST TUNE RECK" + 5 "AbCdEfGhIjK" "alpha1" 99 "27BC71035AAF3DC6" "MAY STAR TIN LYON VEDA STAN" + 6 "OTP's are good" "correct" 0 "D51F3E99BF8E6F0B" "RUST WELT KICK FELL TAIL FRAU" + 7 "OTP's are good" "correct" 1 "82AEB52D943774E4" "FLIT DOSE ALSO MEW DRUM DEFY" + 8 "OTP's are good" "correct" 99 "4F296A74FE1567EC" "AURA ALOE HURL WING BERG WAIT" +} + +foreach {ndx pass seed cnt hex wrds} $tests_sha1 { + test otp-sha1-hex-$ndx "otp-sha1 check hex result" { + list [catch { + set res [::otp::otp-sha1 -hex -seed $seed -count $cnt $pass] + string toupper $res + } msg] $msg + } [list 0 $hex] +} + +foreach {ndx pass seed cnt hex wrds} $tests_sha1 { + test otp-sha1-words-$ndx "otp-sha1 check words encoding" { + list [catch { + set res [::otp::otp-sha1 -words -seed $seed -count $cnt $pass] + } msg] $msg + } [list 0 $wrds] +} + +set tests_rmd160 { + 0 "This is a test." "TeSt" 0 "3A1BFB10A64B4CCD" "SAG SLUG NICE AMOS LUSH CHUM" + 1 "This is a test." "TeSt" 1 "39D56BF655E65DE7" "SAC LAVA WORD LEAD CHEW VAST" + 2 "This is a test." "TeSt" 99 "42F84BA862941033" "UN NAVY THEE NOLL TO HEN" + 3 "AbCdEfGhIjK" "alpha1" 0 "726EDD1BB5DB3642" "DENY DREW YEA COVE LOWE JUG" + 4 "AbCdEfGhIjK" "alpha1" 1 "46A231C501A1D2CE" "YAW ELY DEBT ARK IDA CLAW" + 5 "AbCdEfGhIjK" "alpha1" 99 "848664EF3A300CC9" "FOOL PER SHE DOCK ADD CENT" + 6 "OTP's are good" "correct" 0 "F90D03CC969208C8" "WEAN CLUB VALE NOW JOB CASH" + 7 "OTP's are good" "correct" 1 "B6F5D25A08A90009" "MANA LIEU HELL ELK GREW AVE" + 8 "OTP's are good" "correct" 99 "C890C1F05018BA5F" "ONCE FRAY EROS JADE GINA ONE" +} + +foreach {ndx pass seed cnt hex wrds} $tests_rmd160 { + test otp-rmd160-hex-$ndx "otp-rmd160 check hex result" { + list [catch { + set res [::otp::otp-rmd160 -hex -seed $seed -count $cnt $pass] + string toupper $res + } msg] $msg + } [list 0 $hex] +} + +foreach {ndx pass seed cnt hex wrds} $tests_rmd160 { + test otp-rmd160-words-$ndx "otp-rmd160 check words result" { + list [catch { + set res [::otp::otp-rmd160 -words -seed $seed -count $cnt $pass] + } msg] $msg + } [list 0 $wrds] +} +# ------------------------------------------------------------------------- + +testsuiteCleanup diff --git a/tcllib/modules/otp/pkgIndex.tcl b/tcllib/modules/otp/pkgIndex.tcl new file mode 100644 index 0000000..803854b --- /dev/null +++ b/tcllib/modules/otp/pkgIndex.tcl @@ -0,0 +1,3 @@ +# pkgIndex.tcl -*- tcl -*- +if {![package vsatisfies [package provide Tcl] 8.2]} { return } +package ifneeded otp 1.0.0 [list source [file join $dir otp.tcl]] |