rabbitsign(1)

rabbitsign ๐Ÿ’– โ€” the rabbitsign(1) page, bestie edition ๐ŸŽ€

ok so. this is the manual page for rabbitsign, a General Commands Manual situation. buckle up, we're signing calculator apps and it's gonna be a whole vibe. โœจ


๐ŸŒธ NAME ๐ŸŒธ

rabbitsign โ€” sign applications for TI graphing calculators ๐Ÿ–ฉ๐Ÿ’…


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

no cap, here's how you call her:

rabbitsign [ options ] [ -o appfile ] [ -k keyfile ] hexfile ...

rabbitsign [ options ] [ -k keyfile ] -c hexfile ...

๐Ÿ’œ DESCRIPTION ๐Ÿ’œ

ok so rabbitsign is a whole implementation of Texas Instruments' Rabin and RSA signing algorithms โ€” the exact ones used on the TI-73, TI-83 Plus, TI-84 Plus, TI-89, and TI-92 Plus graphing calculators. iconic lineup tbh. these algorithms are what sign Flash applications and operating systems so the calculator can look at them and go "yep, valid, main character." ๐Ÿ‘‘

the way that rabbitsign works, just like TI's official signing programs, is that it needs a private key โ€” that's a pair of large prime numbers, bestie โ€” to sign apps. and for the app to actually get accepted, the corresponding public key (their product) has to already be present on the calculator. it's giving "you can't sit with us unless you know the password." ๐Ÿ™ˆ

as of this writing, the ``shareware'' private key number 0104, which is the one used for signing applications for the TI-83 Plus and TI-84 Plus, is available through TI's SDK. slay for them. but unfortunately ๐Ÿ˜ญ the OS signing keys, plus the app signing keys for the TI-73, TI-89, and TI-92 Plus, have not been released โ€” which means only TI can sign apps and OSes for those calculators. they're gatekeeping fr fr. ๐Ÿ’€


โœจ OPTIONS โœจ

one bullet per option, every single one, no skipping. let's go. ๐Ÿซถ

  • -a โ€” attempt to match the output of Peter-Martijn Kuipers' appsign program, for testing purposes. the resulting output file will have Unix-style line termination, and hence will not be compatible with all programs. this option is not recommended for ordinary use. ๐Ÿ™…โ™€๏ธ
  • -b โ€” assume input files are raw binary files. if this option is not given, the file type is detected automatically. ๐Ÿงš
  • -c โ€” do not sign apps; instead, check that the signatures of the specified apps are valid. exit status is 0 if all apps are valid, 1 if one or more apps fail, or 2 if there is a non-mathematical error. vibe check mode basically. ๐Ÿ”
  • -f โ€” ignore non-fatal errors, and force the application to be signed if possible. (all of these messages are there for a reason, though, and chances are that if your app generates any of them, it will also either fail validation or crash the calculator. you have been warned.) ๐Ÿ˜ญ
  • -g โ€” write the output file in GraphLink ``TIFL'' format. (by default and for historical reasons, apps and OSes for the TI-73 and TI-83 Plus are written in plain TI Hex format instead; you can use packxxk(1) to convert these files into TIFL format.) apps and OSes for the TI-89 and TI-92 Plus are always written in TIFL format. see APPLICATION FILE FORMATS below for more information. ๐Ÿ’–
  • -k keyfile โ€” read signing and/or validation keys from the given file. this file must be in one of the formats used by TI's SDK tools. (see KEY FILE FORMATS below.) by default, rabbitsign searches for the key named in the app header (for example, 0104.key for ``shareware'' TI-83 Plus apps.) ๐Ÿ—๏ธ
  • -K id โ€” search for the key with the given id (a small hexadecimal number) rather than the ID specified in the app header. ๐Ÿ”Ž
  • -n โ€” attempt to sign the program as-is, without modifying the header. (this option may not produce a file that the calculator will actually accept; it is intended for testing and special-purpose signatures, not for ordinary app signing.) โš ๏ธ
  • -o outfile โ€” specify the output file. by default, output files are named by taking the name of the input file, removing any suffix, and adding a .app or .8xk suffix depending on whether -g is specified. (if the input file already has a .app or .8xk suffix, -signed is inserted, so myapp.8xk becomes myapp-signed.8xk.) โœจ

if - is specified as an input file, that indicates the standard input, and the signed result is written by default to the standard output. ๐Ÿ’ซ

  • -p โ€” fix the app pages header. this is not done by default because an incorrect pages header is generally a sign of a much more serious problem. ๐Ÿšฉ
  • -P โ€” if the application ends close to a page boundary, add an additional page to hold the signature. (application signatures on the TI-73 and TI-83 Plus are not allowed to span a page boundary.) keep in mind that this is extremely wasteful, as it consumes 16384 bytes of Flash to hold approximately 69 bytes of data; if your application is in this situation, you should consider trying to reduce its size slightly, or alternatively, adding more data to take advantage of the extra Flash page. ๐Ÿ’€ so much space for so little, it's giving "buying a whole mansion for one houseplant." ๐Ÿ“
  • -q โ€” do not print non-fatal warning messages. ๐Ÿคซ
  • -r โ€” re-sign a previously signed app (i.e., discard the previous signature before signing.) ๐Ÿ”
  • -R n โ€” for signing TI-73 and TI-83 Plus applications, use root number n (0 โ‰ค n โ‰ค 3) rather than the default, root number 0. all four roots are valid, though distinct, signatures, so this option is mainly for debugging. ๐Ÿ›

root 0 is computed so as to be congruent to m^[(p+1)/4] modulo p and m^[(q+1)/4] modulo q. root 1 is the negation of root 0 modulo p, root 2 the negation modulo q, and root 3 the negation both modulo p and modulo q. math ate, honestly. ๐Ÿงฎโœจ

this option has no effect when signing OSes or TI-89/92 Plus applications, which use the RSA algorithm rather than Rabin. ๐Ÿ™…

  • -t type โ€” explicitly specify the type of program (e.g., 8xk for a TI-83 Plus application, or 73u for a TI-73 operating system.) the default behavior is to infer the program type from the name of the input file. (if the input file does not have a recognized suffix, the type is guessed based on the contents of the program header.) ๐ŸŽ€
  • -u โ€” disable automatic page detection, and assume input files are unsorted. this means that page boundaries must be defined explicitly. (see APPLICATION FILE FORMATS below.) this option has no effect in binary (-b) mode. ๐Ÿฆ‹
  • -v โ€” be verbose; print out the names of apps and their signatures as they are signed. use -vv for more detailed information about the computation. ๐Ÿ—ฃ๏ธ
  • --help โ€” print out a summary of options. ๐Ÿซถ
  • --version โ€” print out version information. โญ

part 2 is coming, bestie โ€” don't go anywhere ๐Ÿ’œ

๐ŸŒˆ APPLICATION FILE FORMATS ๐ŸŒˆ

okay so before you can sign anything, you gotta know what a "app file" even is, and bestie there are like four whole formats. sit down, hydrate, let's go ๐Ÿ’–


๐Ÿงš Intel Hex

Intel hex is a whole standard ASCII file format that basically every PROM programmer on earth speaks, and it's also the format your assembler probably spits out by default. Every single line (they call them "records," fancy) looks like this:

:NNAAAATTDDDDDD...CC

and here's the vibe check on each lil piece:

  • : โ€” the very first character is a colon. that's literally it, it's just there to say "hey, this is Intel hex." nothing deeper ๐Ÿ’…
  • NN โ€” the next two characters are how many data bytes are on this line, written in UPPERCASE ASCII hex. uppercase. we're not being cute about it.
  • AAAA โ€” the next four digits are the address of the data on this line. and listen, rabbitsign only looks at the low 14 bits of that value. the rest? doesn't care, doesn't see it.
  • TT โ€” these two digits are the record "type." Intel hex defines a bunch of record types for all kinds of addressing models, but the only ones that mean anything for TI calculators are type 00 (ordinary data) and type 01 (end of file).
  • DD... โ€” then come 2*NN hex digits, which is the actual data. the real stuff. the payload.
  • CC โ€” finally there's the inverted checksum, and the whole point is that if you add up every byte on the line you get a total of zero modulo 256. cute, right? โœจ (and as a lil extension, rabbitsign lets you put two uppercase Xs in place of a checksum. we're chill like that.)
now the โœจdramaโœจ: since the address is only 16 bits, this format cannot unambiguously represent applications larger than 64 kilobytes. no cap.

so to make multi-page apps possible, rabbitsign tries to detect page boundaries automatically โ€” it starts a new page every time it hits a field with a zero address. so if you wanna build a multi-page app you can literally just concatenate a bunch of Intel Hex files together, like:

cat page0.hex page1.hex | rabbitsign - -o complete.app

the catch (there's always a catch, bestie ๐Ÿ˜ญ): this only works if the records are correctly sorted within each page. if your assembler doesn't generate records in order, you can sort the fields yourself with something like sort -k1.8,1.9 -k1.4,1.7.

wanna turn off that automatic page detection entirely? use the -u option. but then you HAVE to define your page boundaries explicitly using the TI Hex format. no shortcuts, we do it properly ๐Ÿ’…


๐Ÿฆ‹ TI Hex

"TI" hex is an extension on top of Intel hex, and what it does is give you an unambiguous way to represent multi-page apps. it adds records shaped like this:

:0200000200NNCC

which basically means "everything after this lives on relative page number NN." (keep in mind: the TI-83 and 84 Plus install applications "backwards," so if relative page 0 is stored on absolute page 69, then relative page 1 is gonna be on absolute page 68, and so on down the line. yes, really. iconic behavior honestly.)

some assemblers generate multi-page data using type 4 records instead of type 2 โ€” rabbitsign treats those as equivalent to type 2, so don't stress ๐ŸŒธ

and for compatibility with other software that makes certain assumptions about the format, rabbitsign will write 32 bytes per line, and will end lines with a DOS-style carriage return and line feed. old school. retro. we respect the ancestors ๐Ÿซถ


the standard (newer) GraphLink format is a 78-byte binary header that gets slapped onto the start of a hex or binary file. here's what's inside that header, byte by byte:

  • 0x00-07 โ€” the string **TIFL**.
  • 0x08 โ€” the major version number (the "App ID") of the application.
  • 0x09 โ€” the minor version number (the "App Build") of the application.
  • 0x0A โ€” flags; apparently intended to say whether the file contents are binary (0) or TI Hex (1). key word apparently, because this value is not, in fact, set consistently by other software. messy ๐Ÿ’€
  • 0x0B โ€” the "Object Type" field; apparently tells you something about the type of data. it's set to 0x88 in most TI-73 and TI-83 Plus files, and set to 0 in TI-89 and TI-92 Plus files.
  • 0x0C-0F โ€” binary-coded decimal month (one byte), day (one byte), and year (two bytes, big endian) for when the app was signed.
  • 0x10 โ€” length of the app's name.
  • 0x11-18 โ€” name of the app.
  • 0x19-2F โ€” reserved, always set to zero.
  • 0x30 โ€” calculator type (0x73 = TI-83 Plus, 0x74 = TI-73, 0x88 = TI-92 Plus, 0x98 = TI-89).
  • 0x31 โ€” type of data (0x23 = OS upgrade, 0x24 = application, 0x25 = certificate).
  • 0x32-49 โ€” reserved, always set to zero.
  • 0x4A-4D โ€” little endian length of the following data (that's the length of the hex file, not the on-calculator size of the application. important distinction bestie).

there also exist multi-part TIFL files, which are literally just two or more TIFL files concatenated together. (like, say, a software license agreement or a certificate file attached to an application.) rabbitsign handles these in a limited way: it will read only the first section with a recognized data type, and ignore any other data in the file. and heads up โ€” rabbitsign cannot create multi-part TIFL files, but you can make them with packxxk(1) (or honestly just using cat(1), no shame).


๐Ÿ‘‘ Binary

rabbitsign can also read binary app files! they're assumed to be contiguous, which means when you're signing a multi-page app, every page except the last one has to be filled to a full 16k. no gaps, no half-pages, we're filling it all the way up ๐Ÿซถ


๐Ÿ’œ KEY FILE FORMATS ๐Ÿ’œ

key files hold the data you need for signing and validating applications. quick vocab moment:

  • the portion of the key file used for validating is the "public" key
  • the portion used for signing is the "private" key
  • and only the public key is ever stored on the calculator itself ๐Ÿ”

official key files from TI come in two varieties: "Rabin" and "RSA" formats. and ngl, here's the tea: rabbitsign currently supports using Rabin-type key files to generate RSA signatures, but not the other way around. one direction only, bestie.


๐ŸŒธ Rabin key format

the Rabin key file format is typically used for TI-73 and TI-83 Plus application signing keys. it's three lines, each one containing a big integer:

  1. the first line is the public key, n
  2. the second and third lines are its two factors, p and q

each line begins with two hexadecimal digits giving the length of the number in bytes, followed by the bytes themselves, written in hexadecimal in little-endian order. lil prefix, then the goods โœจ


๐ŸŽ€ RSA key format

the RSA key file format is typically used for TI-89 and TI-92 Plus application signing keys. it's three lines:

  1. the key ID
  2. the public key n
  3. the signing exponent d
quick math moment: d is the inverse of the validation exponent, 17, modulo ฯ•(n) โ€” which means calculating d is computationally equivalent to factoring n. yeah. that's the whole security of the thing. respect the math ๐Ÿ’…

the key ID is a short hexadecimal number, and it should match the contents of the 811x header field. the numbers n and d are written as big integers, exactly like in the Rabin key format. consistency, we love her.


๐Ÿ—‚๏ธ FILES ๐Ÿ—‚๏ธ

  • /usr/local/share/rabbitsign/*.key โ€” private key files which will be used if the requested key is not found in the current directory.

๐Ÿ’€ BUGS ๐Ÿ’€

who needs them? ๐Ÿ˜Œ

rabbitsign accepts keys, applications, and even file names which cause TI's programs to crash or generate invalid signatures. (we're built different. not always in a good way.)

some apps which come very close to filling the last page may not be usable with TI-Connect. this is a bug in TI-Connect, not us. try TiLP instead, bestie ๐Ÿซถ

rabbitsign does not always generate the same signature as do TI's programs. this is not a bug โ€” it's just the differences in implementation, periodt. there are in fact four valid signatures for every application hash, and all four are accepted by the calculator. so like, it's fine. it's fine!

and listen, seriously for a second: if you encounter a valid app which rabbitsign is unable to sign, or worse, generates an invalid signature โ€” that is a serious bug, and I would like to know about it. please tell me, I'm begging ๐Ÿ™ˆ


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

packxxk(1), rskeygen(1)


๐Ÿ’– AUTHOR ๐Ÿ’–

Benjamin Moody <floppusmaximus@users.sf.net>


and that's the whole page, bestie!! this was RabbitSign 2.0, from July 2009, aka rabbitsign(1) โ€” go forth and sign some apps, you absolute icon ๐Ÿ‘‘โœจ

๐Ÿ“ฆ where this page comes from