Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Skipjack encryption for 3.0/7.0

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Skipjack encryption for 3.0/7.0

    #IF 0
    Code:
    =====================================================================
                          Skipjack Encryption Algorithm
    =====================================================================
       
    Four FIPS-approved symmetric key algorithms exist for encryption: AES 
    (Rijndael), DES, triple-DES, and Skipjack.  Skipjack is free for any 
    use public or private, commercial or non-commercial.  
       
    Information about the algorithm and its implementation can be found in 
    the following documents: 
     http://csrc.nist.gov/encryption/skipjack/skipjack.pdf 
     http://csrc.nist.gov/encryption/skip...rification.pdf 
       
    Bruce Schneier's interesting overview of Skipjack's origin and design is 
    available at: 
     http://www.counterpane.com/crypto-gram-9807.html#skip 
       
    The PB code appearing here is based in part on an implementation 
    written, optimized, and placed in the public domain by Panu Rissanen, 
    Mark Tillotson, Paulo Barreto. 
       
    This PB implementation is hereby placed in the public domain.  Use it 
    as you wish.  My hope is discourage reliance on home-grown encryption 
    schemes in favor of well-examined, strong, freely available 
    algorithms. 
       
    In this posting, test-bed code appears below the SKIPJACK.BAS file 
    contents.  All code requires compiler releases 3.0/7.0 or later. 
       
       
    <U>Implementation Notes</U>
    -- The algorithm operates on plaintext blocks of 8 bytes with a user key 
    limited to 10 bytes (80 bits).  Encryption of shorter blocks is possible 
    only by padding the plaintext (often with zero bytes), which can be 
    accomplished through several methods.  The simplest of them assumes that 
    the final byte of plaintext always identifies the number of bytes of 
    padding added, including the final byte itself. 
       
    Examples: 
       
       total plaintext bytes         = 30
       plaintext blocks encrypted:   = 4
       final block                   = chr$(x1 to x6) + chr$(0,2)
       
       total plaintext bytes         = 42
       plaintext blocks encrypted:   = 6
       final block                   = chr$(x1 to x2) + chr$(0,0,0,0,0,6)
       
    -- Implementation here is handled through an #INCLUDE file.  No global 
    data is employed.  
       
    -- As presented, the code does not supply a ready-to-use encryption 
    application.  It offers necessary pieces only, as well as an 
    illustration of their use.  Always keep in mind that most encryption 
    is broken because of implementation flaws and weaknesses. 
       
    -- Because of the methods of data handling required for most 
    encryption and hashing, PowerBASIC's LONGs should be used to assure  
    correct bit-level results (as well as additional speed). 
       
    Greg Turgeon 09/2002
       
    #ENDIF
       
    DEFLNG A-Z
       
    '%ROUNDS      = 32
    %BLOCKSIZE   = 8
    %KEYSIZE     = 10
    %SUBKEY_SIZE = (10*256)
       
    TYPE ENCRYPTION_CONTEXT
       UserKeyLength AS LONG
       UserKey       AS BYTE PTR
       InBlock       AS BYTE PTR
       OutBlock      AS BYTE PTR
       Table         AS BYTE PTR
       Key           AS BYTE PTR              '<-- pointer to encryption subkey buffer
       Key_Buffer    AS STRING * %SUBKEY_SIZE '<-- encryption subkey buffer
    END TYPE
       
    '--------------------
    '-- Utility macros
    '--------------------
    MACRO zbs(xx)=string$(xx,0)
       
    '--------------------
    MACRO FUNCTION shl8(xx)
    retval = (xx)
    !  shl   retval, 8
    END MACRO = retval
       
    '--------------------
    MACRO FUNCTION byte1(xx)
    retval = (xx)
    !  mov   eax, retval
    !  shr   eax, 8
    !  and   eax, &hff
    !  mov   retval, eax
    END MACRO = retval
       
       
    '--------------------
    '-- Skipjack macros
    '--------------------
    MACRO g(w,i,j,k,l)
    t = Ctx.@Key[(w AND &hff) of 255, i of 3] : w = w XOR shl8(t)
    t = Ctx.@Key[byte1(w) of 255,     j of 3] : w = w XOR t
    t = Ctx.@Key[(w AND &hff) of 255, k of 3] : w = w XOR shl8(t)
    t = Ctx.@Key[byte1(w) of 255,     l of 3] : w = w XOR t
    END MACRO
       
    '--------------------
    MACRO g0(w)
    g(w,0,1,2,3)
    END MACRO
       
    '--------------------
    MACRO g1(w)
    g(w,4,5,6,7)
    END MACRO
       
    '--------------------
    MACRO g2(w)
    g(w,8,9,0,1)
    END MACRO
       
    '--------------------
    MACRO g3(w)
    g(w,2,3,4,5)
    END MACRO
       
    '--------------------
    MACRO g4(w)
    g(w,6,7,8,9)
    END MACRO
       
    '--------------------
    MACRO h(w,i,j,k,l)
    t = Ctx.@Key[byte1(w) of 255,     l of 3] : w = w XOR t
    t = Ctx.@Key[(w AND &hff) of 255, k of 3] : w = w XOR shl8(t)
    t = Ctx.@Key[byte1(w) of 255,     j of 3] : w = w XOR t
    t = Ctx.@Key[(w AND &hff) of 255, i of 3] : w = w XOR shl8(t)
    END MACRO
       
    '--------------------
    MACRO h0(w)
    h(w,0,1,2,3)
    END MACRO
       
    '--------------------
    MACRO h1(w)
    h(w,4,5,6,7)
    END MACRO
       
    '--------------------
    MACRO h2(w)
    h(w,8,9,0,1)
    END MACRO
       
    '--------------------
    MACRO h3(w)
    h(w,2,3,4,5)
    END MACRO
       
    '--------------------
    MACRO h4(w)
    h(w,6,7,8,9)
    END MACRO
       
       
    DECLARE FUNCTION SkipJack_Init&(Ctx AS ENCRYPTION_CONTEXT)
    DECLARE FUNCTION Set_Key&(Ctx AS ENCRYPTION_CONTEXT)
    DECLARE FUNCTION EncryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
    DECLARE FUNCTION DecryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
       
       
    '====================
    FUNCTION Set_Key&(Ctx AS ENCRYPTION_CONTEXT)
    if Skipjack_Init(Ctx) = 0 then
       function = 0 : exit function
    end if
    REGISTER i&, j&
    LOCAL k AS BYTE PTR, uk AS BYTE PTR
    k = Ctx.Key : uk = Ctx.UserKey
    for i = 0 to 9
       for j = 0 to 255
          @k = Ctx.@Table[j XOR @uk] : incr k
       next j
       incr uk
    next i
    function = -1
    END FUNCTION
       
       
    '====================
    FUNCTION EncryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
    LOCAL w1&, w2&, w3&, w4&, t&, retval&
       
    w1 = shl8(Ctx.@InBlock[0]) + Ctx.@InBlock[1]
    w2 = shl8(Ctx.@InBlock[2]) + Ctx.@InBlock[3]
    w3 = shl8(Ctx.@InBlock[4]) + Ctx.@InBlock[5]
    w4 = shl8(Ctx.@InBlock[6]) + Ctx.@InBlock[7]
       
    g0(w1) : w4 = w4 XOR w1 XOR 1
    g1(w4) : w3 = w3 XOR w4 XOR 2
    g2(w3) : w2 = w2 XOR w3 XOR 3
    g3(w2) : w1 = w1 XOR w2 XOR 4
    g4(w1) : w4 = w4 XOR w1 XOR 5
    g0(w4) : w3 = w3 XOR w4 XOR 6
    g1(w3) : w2 = w2 XOR w3 XOR 7
    g2(w2) : w1 = w1 XOR w2 XOR 8
       
    w2 = w2 XOR w1 XOR  9 : g3(w1)
    w1 = w1 XOR w4 XOR 10 : g4(w4)
    w4 = w4 XOR w3 XOR 11 : g0(w3)
    w3 = w3 XOR w2 XOR 12 : g1(w2)
    w2 = w2 XOR w1 XOR 13 : g2(w1)
    w1 = w1 XOR w4 XOR 14 : g3(w4)
    w4 = w4 XOR w3 XOR 15 : g4(w3)
    w3 = w3 XOR w2 XOR 16 : g0(w2)
       
    g1(w1) : w4 = w4 XOR w1 XOR 17
    g2(w4) : w3 = w3 XOR w4 XOR 18
    g3(w3) : w2 = w2 XOR w3 XOR 19
    g4(w2) : w1 = w1 XOR w2 XOR 20
    g0(w1) : w4 = w4 XOR w1 XOR 21
    g1(w4) : w3 = w3 XOR w4 XOR 22
    g2(w3) : w2 = w2 XOR w3 XOR 23
    g3(w2) : w1 = w1 XOR w2 XOR 24
       
    w2 = w2 XOR w1 XOR 25 : g4(w1)
    w1 = w1 XOR w4 XOR 26 : g0(w4)
    w4 = w4 XOR w3 XOR 27 : g1(w3)
    w3 = w3 XOR w2 XOR 28 : g2(w2)
    w2 = w2 XOR w1 XOR 29 : g3(w1)
    w1 = w1 XOR w4 XOR 30 : g4(w4)
    w4 = w4 XOR w3 XOR 31 : g0(w3)
    w3 = w3 XOR w2 XOR 32 : g1(w2)
       
    Ctx.@OutBlock[0] = byte1(w1) : Ctx.@OutBlock[1] = w1 AND &hff
    Ctx.@OutBlock[2] = byte1(w2) : Ctx.@OutBlock[3] = w2 AND &hff
    Ctx.@OutBlock[4] = byte1(w3) : Ctx.@OutBlock[5] = w3 AND &hff
    Ctx.@OutBlock[6] = byte1(w4) : Ctx.@OutBlock[7] = w4 AND &hff
    END FUNCTION
       
       
    '====================
    FUNCTION DecryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
    LOCAL w1&, w2&, w3&, w4&, t&, retval&
       
    w1 = shl8(Ctx.@InBlock[0]) + Ctx.@InBlock[1]
    w2 = shl8(Ctx.@InBlock[2]) + Ctx.@InBlock[3]
    w3 = shl8(Ctx.@InBlock[4]) + Ctx.@InBlock[5]
    w4 = shl8(Ctx.@InBlock[6]) + Ctx.@InBlock[7]
       
    h1(w2) : w3 = w3 XOR w2 XOR 32
    h0(w3) : w4 = w4 XOR w3 XOR 31
    h4(w4) : w1 = w1 XOR w4 XOR 30
    h3(w1) : w2 = w2 XOR w1 XOR 29
    h2(w2) : w3 = w3 XOR w2 XOR 28
    h1(w3) : w4 = w4 XOR w3 XOR 27
    h0(w4) : w1 = w1 XOR w4 XOR 26
    h4(w1) : w2 = w2 XOR w1 XOR 25
       
    w1 = w1 XOR w2 XOR 24 : h3(w2)
    w2 = w2 XOR w3 XOR 23 : h2(w3)
    w3 = w3 XOR w4 XOR 22 : h1(w4)
    w4 = w4 XOR w1 XOR 21 : h0(w1)
    w1 = w1 XOR w2 XOR 20 : h4(w2)
    w2 = w2 XOR w3 XOR 19 : h3(w3)
    w3 = w3 XOR w4 XOR 18 : h2(w4)
    w4 = w4 XOR w1 XOR 17 : h1(w1)
       
    h0(w2) : w3 = w3 XOR w2 XOR 16
    h4(w3) : w4 = w4 XOR w3 XOR 15
    h3(w4) : w1 = w1 XOR w4 XOR 14
    h2(w1) : w2 = w2 XOR w1 XOR 13
    h1(w2) : w3 = w3 XOR w2 XOR 12
    h0(w3) : w4 = w4 XOR w3 XOR 11
    h4(w4) : w1 = w1 XOR w4 XOR 10
    h3(w1) : w2 = w2 XOR w1 XOR  9 
       
    w1 = w1 XOR w2 XOR 8 : h2(w2)
    w2 = w2 XOR w3 XOR 7 : h1(w3)
    w3 = w3 XOR w4 XOR 6 : h0(w4)
    w4 = w4 XOR w1 XOR 5 : h4(w1)
    w1 = w1 XOR w2 XOR 4 : h3(w2)
    w2 = w2 XOR w3 XOR 3 : h2(w3)
    w3 = w3 XOR w4 XOR 2 : h1(w4)
    w4 = w4 XOR w1 XOR 1 : h0(w1)
       
    Ctx.@OutBlock[0] = byte1(w1) : Ctx.@OutBlock[1] = w1 AND &hff
    Ctx.@OutBlock[2] = byte1(w2) : Ctx.@OutBlock[3] = w2 AND &hff
    Ctx.@OutBlock[4] = byte1(w3) : Ctx.@OutBlock[5] = w3 AND &hff
    Ctx.@OutBlock[6] = byte1(w4) : Ctx.@OutBlock[7] = w4 AND &hff
    END FUNCTION
       
       
    '====================
    FUNCTION SkipJack_Init&(Ctx AS ENCRYPTION_CONTEXT)
    if (Ctx.UserKeylength <> %KEYSIZE) then
       function = 0 : exit function
    end if
       
    Ctx.Key_Buffer = zbs(%SUBKEY_SIZE)
    Ctx.Key        = varptr(Ctx.Key_Buffer)
    Ctx.Table      = codeptr(fTable)
    function = -1
    exit function
    fTable:
    !DB &ha3,&hd7,&h09,&h83,&hf8,&h48,&hf6,&hf4,&hb3,&h21,&h15,&h78,&h99,&hb1,&haf,&hf9
    !DB &he7,&h2d,&h4d,&h8a,&hce,&h4c,&hca,&h2e,&h52,&h95,&hd9,&h1e,&h4e,&h38,&h44,&h28
    !DB &h0a,&hdf,&h02,&ha0,&h17,&hf1,&h60,&h68,&h12,&hb7,&h7a,&hc3,&he9,&hfa,&h3d,&h53
    !DB &h96,&h84,&h6b,&hba,&hf2,&h63,&h9a,&h19,&h7c,&hae,&he5,&hf5,&hf7,&h16,&h6a,&ha2
    !DB &h39,&hb6,&h7b,&h0f,&hc1,&h93,&h81,&h1b,&hee,&hb4,&h1a,&hea,&hd0,&h91,&h2f,&hb8
    !DB &h55,&hb9,&hda,&h85,&h3f,&h41,&hbf,&he0,&h5a,&h58,&h80,&h5f,&h66,&h0b,&hd8,&h90
    !DB &h35,&hd5,&hc0,&ha7,&h33,&h06,&h65,&h69,&h45,&h00,&h94,&h56,&h6d,&h98,&h9b,&h76
    !DB &h97,&hfc,&hb2,&hc2,&hb0,&hfe,&hdb,&h20,&he1,&heb,&hd6,&he4,&hdd,&h47,&h4a,&h1d
    !DB &h42,&hed,&h9e,&h6e,&h49,&h3c,&hcd,&h43,&h27,&hd2,&h07,&hd4,&hde,&hc7,&h67,&h18
    !DB &h89,&hcb,&h30,&h1f,&h8d,&hc6,&h8f,&haa,&hc8,&h74,&hdc,&hc9,&h5d,&h5c,&h31,&ha4
    !DB &h70,&h88,&h61,&h2c,&h9f,&h0d,&h2b,&h87,&h50,&h82,&h54,&h64,&h26,&h7d,&h03,&h40
    !DB &h34,&h4b,&h1c,&h73,&hd1,&hc4,&hfd,&h3b,&hcc,&hfb,&h7f,&hab,&he6,&h3e,&h5b,&ha5
    !DB &had,&h04,&h23,&h9c,&h14,&h51,&h22,&hf0,&h29,&h79,&h71,&h7e,&hff,&h8c,&h0e,&he2
    !DB &h0c,&hef,&hbc,&h72,&h75,&h6f,&h37,&ha1,&hec,&hd3,&h8e,&h62,&h8b,&h86,&h10,&he8
    !DB &h08,&h77,&h11,&hbe,&h92,&h4f,&h24,&hc5,&h32,&h36,&h9d,&hcf,&hf3,&ha6,&hbb,&hac
    !DB &h5e,&h6c,&ha9,&h13,&h57,&h25,&hb5,&he3,&hbd,&ha8,&h3a,&h01,&h05,&h59,&h2a,&h46
    END FUNCTION
    '-- end SKIPJACK.BAS
       
       
    '=====================================================================
    '                       Skipjack Test Bed code
    '             Compiles with either PBWIN 7.0+ or PBCC 3.0+
    '=====================================================================
    #COMPILE EXE
    #REGISTER NONE
    #DIM ALL
    '============
    DEFLNG A-Z
       
    '--------------------
    '-- Utility macros
    '--------------------
       
    #IF %def(%pb_win32)
       MACRO eol=$CR
       MACRO mbox(t)=msgbox t
    #ELSEIF %def(%pb_cc32)
       MACRO eol=$CRLF
       MACRO mbox(t)=stdout t
    #ENDIF
       
    '--------------------
    MACRO EnterCC
    #IF %def(%pb_cc32)
       LOCAL launched&
       if (cursory = 1) and (cursorx = 1) then launched = -1
    #ENDIF
    END MACRO
       
    '--------------------
    MACRO ExitCC
    #IF %def(%pb_cc32)
       if launched then
          input flush
          stdout "Press any key to end";
          waitkey$
       end if
    #ENDIF 
    END MACRO
       
    '--------------------  
    'MACRO zbs(x)=string$(x,0) 'also defined in SKIPJACK.BAS
       
    #INCLUDE "SKIPJACK.BAS"
       
    DECLARE FUNCTION Hex2Show$(Buffer$)
       
    '====================
    FUNCTION PBMain&()
    REGISTER i&
    LOCAL key$, plain$, cipher$, shouldbe$, t$
    LOCAL ctx AS ENCRYPTION_CONTEXT  ' defined in SKIPJACK.BAS
    EnterCC
       
    '-- Standard test vectors
    key      = chr$(&h00, &h99, &h88, &h77, &h66, &h55, &h44, &h33, &h22, &h11)
    plain    = chr$(&h33, &h22, &h11, &h00, &hdd, &hcc, &hbb, &haa)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&h25, &h87, &hca, &he2, &h7a, &h12, &hd3, &h00)
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
    key      = chr$(&he7,&h49,&h6e,&h99,&he4,&h62,&h8b,&h7f,&h9f,&hfb)
    plain    = chr$(&h99,&hcc,&hfe,&h2b,&h90,&hfd,&h55,&h0b)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&h60,&ha7,&h3d,&h38,&h7b,&h51,&h7f,&hca)
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      = chr$(&he7,&h49,&h6e,&h99,&he4,&h62,&h8b,&h7f,&h9f,&hfb)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
    key      = chr$(&hf8,&hda,&h02,&h64,&h77,&h22,&hf7,&h10,&h3a,&hdf)
    plain    = chr$(&h1d,&hdf,&h39,&hab,&hf5,&hcd,&h71,&h1e)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&hc9,&h2d,&h22,&h32,&h4c,&h6b,&h31,&hae)
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      = chr$(&hf8,&hda,&h02,&h64,&h77,&h22,&hf7,&h10,&h3a,&hdf)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol + eol
       
    key      = chr$(&h5b,&h87,&h8e,&h0b,&h22,&ha7,&h05,&hac,&hf8,&hfb)
    plain    = chr$(&h0c,&h48,&h9b,&h66,&he2,&hda,&h53,&h1b)
    cipher   = zbs(len(plain))
    shouldbe = chr$(&h6e,&h93,&h70,&ha9,&h1b,&h99,&h48,&h78)
    t = t + "Key length (bits):" + str$(len(key)*8) + eol
    t = t + "plain:    " + Hex2Show$(plain) + eol
    gosub DoEncrypt
    t = t + "cipher:   " + Hex2Show$(cipher) + eol
    t = t + "shouldbe: " + Hex2Show$(shouldbe) + eol
    '-- Be sure to reload key$
    key      = chr$(&h5b,&h87,&h8e,&h0b,&h22,&ha7,&h05,&hac,&hf8,&hfb)
    gosub DoDecrypt
    t = t + "plain:    " + Hex2Show$(plain) + eol
       
    mbox(t)
       
    ExitCC
    exit function
       
    '============
    DoEncrypt:
    ctx.UserKey       = strptr(key)
    ctx.UserKeyLength = len(key)
    ctx.InBlock       = strptr(plain)
    ctx.OutBlock      = strptr(cipher)
    if Set_Key&(ctx) then 
       for i = 1 to (len(plain)\%BLOCKSIZE)  '<-- Required: (len(plain$) mod 8) = 0
          EncryptBlock ctx
          ctx.InBlock  = ctx.InBlock  + %BLOCKSIZE
          ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
       next i&
    else
       mbox("Encrypt SetKey Error")
    end if
    '-- Burn the subkey
    if Ctx.Key then poke$ Ctx.Key, zbs(sizeof(Ctx.Key_Buffer))
    RETURN
       
    '============
    DoDecrypt:
    ctx.UserKey       = strptr(key)
    ctx.UserKeyLength = len(key)
    ctx.InBlock       = strptr(cipher)
    ctx.OutBlock      = strptr(plain)
    if Set_Key&(ctx) then 
       for i = 1 to (len(plain)\%BLOCKSIZE)  '<-- Required: (len(plain$) mod 8) = 0
          DecryptBlock ctx
          ctx.InBlock  = ctx.InBlock  + %BLOCKSIZE
          ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
       next i
    else
       mbox("Decrypt SetKey Error")
    end if
    '-- Burn the subkey
    if Ctx.Key then poke$ Ctx.Key, zbs(sizeof(Ctx.Key_Buffer))
    RETURN
    END FUNCTION
       
       
    '====================
    FUNCTION Hex2Show$(Buffer$)
    LOCAL t$, i&, b AS BYTE PTR
    b = strptr(Buffer$)
    for i = 0 to len(Buffer$)-1
       t = t + hex$(@b[i],2) + " "
    next i
    function = t
    END FUNCTION
    '-- end TESTBED.BAS
    ------------------
    -- Greg
    gturgeon@compuserve.com
Working...
X