'Subject: Decryption using the Chinese remainder theorem.
'Author : Sjoerd.J.Schaper
'Date   : 03-13-2005
'Code   : QuickBasic, PDS, VBdos, FreeBasic
REM $LANG: "qb"
REM $INCLUDE: 'largeint.bi'
DECLARE SUB readkey (n, g$)
'read base 64 data
CONST P = 0, Q = 1, dP = 2, dQ = 3
CONST Q1 = 4, i0 = 5, i1 = 6
t = LargeInit(i1, "decoder")
DIM pc AS LONG, pp AS LONG
DIM byt AS STRING * 1, b4 AS STRING * 4
DIM g(4) AS STRING, wdir AS STRING
wdir = SPACE$(64): Work wdir '         working directory
CLS : tim# = TIMER

begin:
LOCATE 1, 1
PRINT "   +---------------------------------------------------+"
PRINT "   |  input: filenames for                             |"
PRINT "   |  private key, ciphertext and message, 0 to exit.  |"
PRINT "   |                                                   |"
PRINT "   +---------------------------------------------------+"
LOCATE 4, 7: INPUT ; "k"; g(0)
IF INSTR(g(0), "'") THEN GOTO begin
IF g(0) = "" OR g(0) = "0" THEN GOTO eind
k = FREEFILE
OPEN wdir + g(0) FOR INPUT AS k
   FOR t = 0 TO 4 '                    read prime factors,
      INPUT #k, g(t) '                 Crt exponents & Crt coefficient
   NEXT t '            
CLOSE k
'
readkey P, g(0): readkey Q, g(1)
readkey dP, g(2): readkey dQ, g(3)
readkey Q1, g(4)
Dup Q, i0: Modmlt i0, Q1, P
IF NOT Isf(i0, 1) THEN '               check
   LOCATE 7, 1: Prints " invalid keyfile", 1
   GOTO eind
END IF
'
INPUT ; " c"; g(0): Cfile = FREEFILE
OPEN wdir + g(0) FOR BINARY AS Cfile ' cipher
INPUT ; " m"; g(0): Pfile = FREEFILE
OPEN wdir + g(0) FOR BINARY AS Pfile ' plaintext
INPUT " fl"; g(0): fl = 0 '            set flag to Print Scrn
IF INSTR(LCASE$(g(0)), "verb") THEN fl = -1

GET #Cfile, 1, b4
LOCATE 7, 1: pc = CVL(b4)
pp = pc \ 512: k = pc - pp * 512 '     len(Pfile), len(modulus)
ks = k - 9 '                           seasoning space
s = pp \ ks: u = pp - CLNG(s) * ks '   total records, byte remainder
IF u > 0 THEN s = s + 1

pc = 4: pp = 0 '                       initial positions
FOR r = 1 TO s
   Letf i0, 0
   FOR t = 1 TO k '                    convert cipher to base MB
      GET #Cfile, pc + t, byt
      Inc i0, ASC(byt)
      IF t < k THEN Lsft i0, 8
   NEXT t
   pc = pc + k
   '
   Dup i0, i1
   Modpwr i0, dP, P '                  i0:= c^ dP (mod P)
   Modpwr i1, dQ, Q '                  i1:= c^ dQ (mod Q)
   Subt i0, i1: Mult i0, Q1, t0 '      Chinese recombination
   Moddiv t0, P: Mult t0, Q, i0
   Add i0, i1: Rsft i0, 64 '           desalinate
   '
   FOR t = 1 TO ks '                   write message octets
      a = Mp2(i0, 256)
      Rsft i0, 8: byt = CHR$(a)
      PUT #Pfile, pp + t, byt
      IF fl AND (a <> 13) THEN '       print to screen
         PRINT byt;
      END IF
      IF r = s AND t = u THEN EXIT FOR
   NEXT t
   pp = pp + ks
   '
   IF NOT fl THEN PRINT "*";
NEXT r

CLOSE Pfile
CLOSE Cfile
GOTO begin

eind:
LOCATE 24, 1
g(0) = STR$(CSNG(TIMER - tim#))
Prints " Timer:" + g(0) + " s", 0
CALL Term
SYSTEM

SUB readkey (n, g$)
b64$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
   '
   IF RIGHT$(g$, 1) = "=" THEN i = 1
   IF RIGHT$(g$, 2) = "==" THEN i = 2
   Letf n, 0: k = LEN(g$) - i
   FOR t = 1 TO k '                    base-64 to largeint
      j = INSTR(b64$, MID$(g$, t, 1))
      IF j > 0 THEN Inc n, j - 1
      IF t < k THEN Lsft n, 6
   NEXT t
   IF i > 0 THEN Rsft n, i * 2
END SUB

