2024-04-29

Navigation

Skip Navigation Links

Hash algorithms

Asymmetric Algorithms

Symmetric Cipher Algorithms

Encoding Algorithms

Compression Algorithms

Pseudo Random Number Algorithms

Steganography

Library Wrappers

String Comparison

Others

Syntax highlighting by Prism
PBCrypto.com Mirror

Skipjack

Algorithm creator(s)

NSA


PB author(s)

Greg Turgeon


Description

Skipjack, well known for its use in the Clipper program, is an unbalanced Feistel network, a product of military cryptography. It is a 64-bit symmetric block cipher with an 80-bit key, and is about twice as fast as DES on 32-bit microprocessors.


Note

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 by padding the plaintext (often with zero bytes), which can be accomplished through several methods.


Source

https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24146-skipjack-encryption-for-3-0-7-0?t=23509


See also

n/a


Source Code

Download source code file skipjack.bas (Right-click -> "Save as ...")

#IF 0 
=====================================================================
                      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/skipjack/clarification.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. Implementation Notes 
-- 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 



'SKIPJACK.BAS
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 





'-- TESTBED.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

Mirror provided by Knuth Konrad