Rijndael
Algorithm creator(s)
Joan Daemen, Vincent Rijmen
PB author(s)
Greg Turgeon
Description
PBCC3/PBWIN7 implementation of Rijndael - the AES (Advanced Encryption Standard) cipher. Rijndael is relatively fast, has a design heavily influenced by the block cipher Square, and features variable block and key lengths (128, 192, or 256 bits).
Note
See also Steven Pringels' PBCC2/PBDLL6 implementation (suitable for all versions of PowerBASIC). Note that Steven Pringel's port uses a fixed block length of 256 bits, likewise the key is expanded to 256 bits. Greg Turgeon's sample is the implementation of Rijndael which specifies a block length of only 128 bits.
Source
https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24101-rijndael-encryption-aes-for-3-0-7-0?t=23464
See also
Source Code
Download source code file rijndael.bas (Right-click -> "Save as ...")
#IF 0
=====================================================================
Rijndael Encryption
=====================================================================
Rijndael has been selected by the NIST as "the AES [Advanced
Encryption Standard] algorithm" and is described in FIPS-197, which is
available here: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
Rijndael is free for any use public or private, commercial or
non-commercial. The authors of Rijndael provide a home page for the
algorithm: http://www.esat.kuleuven.ac.be/~rijmen/rijndael/
The PowerBASIC implementation appearing below, which meets the AES
standard for 16-byte block operations, is based in part on java
routines written and placed in the public domain by Paulo Barreto.
The 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 RIJNDAEL.BAS file
contents. All code requires compiler releases 3.0/7.0 or later.
Implementation Notes
-- The algorithm operates on plaintext blocks of 16 bytes. 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: = 2
final block = chr$(x1 to x14) + chr$(0,2)
total plaintext bytes = 40
plaintext blocks encrypted: = 3
final block = chr$(x1 to x8) + chr$(0,0,0,0,0,0,0,8)
-- Encryption key lengths can range from 1 to 32 bytes (8 to 256 bits).
-- 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.
-- Like most encryption algorithms, Rijndael was designed on
big-endian systems. For this reason, little-endian systems return
correct test vector results only through considerable byte-swapping,
with efficiency suffering as a result. Because it adds nothing to the
encryption security, an efficient implementation should avoid the
byte-swapping. Here the equate %VERIFY_IMPLEMENTATION can be remmed
to avoid this byte-swapping.
-- 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 08/2002
#ENDIF
'-- Rem this equate for any use other than verification of implementation.
'#########################################################################
%VERIFY_IMPLEMENTATION = 1
DEFLNG A-Z
%MAX_ROUNDS = 14
%MIN_ROUNDS = 10
%BLOCKSIZE = 16
%SUBKEY_SIZE = (%BLOCKSIZE*2*8) '256
%MAX_KEY_BYTES = (%BLOCKSIZE*2)
%ENCRYPT = 1
%DECRYPT = 2
TYPE ENCRYPTION_CONTEXT
Action AS LONG
Rounds AS LONG
UserKeyLength AS LONG
UserKey AS LONG PTR
InBlock AS LONG PTR
OutBlock AS LONG PTR
KeyBlocks AS LONG '4*4-byte blocks
KE AS LONG PTR '<-- pointer to encryption subkey buffer
KE_Buffer AS STRING * %SUBKEY_SIZE '<-- encryption subkey buffer
KD AS LONG PTR '<-- pointer to decryption subkey buffer
KD_Buffer AS STRING * %SUBKEY_SIZE '<-- decryption subkey buffer
Se AS BYTE PTR
Sd AS BYTE PTR
Te0 AS LONG PTR
Te1 AS LONG PTR
Te2 AS LONG PTR
Te3 AS LONG PTR
Td0 AS LONG PTR
Td1 AS LONG PTR
Td2 AS LONG PTR
Td3 AS LONG PTR
Rcon AS LONG PTR
END TYPE
'--------------------
'-- Utility macros
'--------------------
MACRO zbs(xx)=string$(xx,0)
'--------------------
MACRO FUNCTION shiftlc(xx,constant_shiftval)
retval = (xx)
! shl retval, constant_shiftval
END MACRO = retval
'--------------------
MACRO FUNCTION shiftrc(xx,constant_shiftval)
retval = (xx)
! shr retval, constant_shiftval
END MACRO = retval
'--------------------
MACRO FUNCTION byte3(xx)
retval = (xx)
! mov eax, retval
! shr eax, 24
! mov retval, eax
END MACRO = retval
'--------------------
MACRO FUNCTION byte2(xx)
retval = (xx)
! mov eax, retval
! shr eax, 16
! and eax, &hff
! mov retval, eax
END MACRO = retval
'--------------------
MACRO FUNCTION byte1(xx)
retval = (xx)
! mov eax, retval
! shr eax, 8
! and eax, &hff
! mov retval, eax
END MACRO = retval
'--------------------
MACRO FUNCTION byte0(xx)
retval = (xx)
! mov eax, retval
! and eax, &hff
! mov retval, eax
END MACRO = retval
'--------------------
MACRO FUNCTION get_block(mem_ptr)
! mov edx, mem_ptr
! mov eax, [edx]
#IF %def(%VERIFY_IMPLEMENTATION)
! bswap eax
#ENDIF
! mov retval, eax
! add edx, 4
! mov mem_ptr, edx
END MACRO = retval
'--------------------
MACRO put_block(mem_ptr,value)
retval=value
! mov edx, retval
#IF %def(%VERIFY_IMPLEMENTATION)
! bswap edx
#ENDIF
! mov eax, mem_ptr
! mov [eax], edx
! add eax, 4
! mov mem_ptr, eax
END MACRO
DECLARE FUNCTION Rijndael_Init&(Ctx AS ENCRYPTION_CONTEXT)
DECLARE FUNCTION Set_Key&(Ctx AS ENCRYPTION_CONTEXT)
DECLARE FUNCTION MakeDecryptKeySchedule(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)
LOCAL i&, n&, nk&, pblock&, r&, temp&, t&, u&, v&, retval&
LOCAL in_ukey$, in_key AS LONG PTR, k AS LONG PTR, s AS BYTE PTR
select case as long Ctx.UserKeyLength
case 16
Ctx.Rounds = 10
case 24
Ctx.Rounds = 12
case 32
Ctx.Rounds = 14
case else
function = 0
exit function
end select
Ctx.KeyBlocks = (Ctx.Rounds+1)*4
Rijndael_Init Ctx
in_ukey$ = zbs(%MAX_KEY_BYTES)
in_key = strptr(in_ukey$)
pblock = Ctx.UserKey
k = Ctx.KE 'local copy
for i = 0 to (Ctx.Rounds-6)-1
@k[i] = get_block(pblock)
next i
s = Ctx.Se
i = Ctx.Rounds - 6 : nk = i : n = 0
do while i < Ctx.KeyBlocks
temp = @k[i-1]
if n = 0 then
n = Nk
t = byte2(temp)
v = shiftlc(@s[t],24)
t = byte1(temp) : u = shiftlc(@s[t],16)
v = v OR u
t = byte0(temp) : u = shiftlc(@s[t],8)
v = v OR u
u = @s[byte3(temp)]
temp = (v OR u) XOR Ctx.@Rcon[r] : incr r
else
if ((Nk = 8) AND (n = 4)) then
t = byte3(temp)
v = shiftlc(@s[t],24)
t = byte2(temp) : u = shiftlc(@s[t],16)
v = v OR u
t = byte1(temp) : u = shiftlc(@s[t],8)
v = v OR u
u = @s[temp AND &hff]
temp = v OR u
end if
end if
@k[i] = @k[i-nk] XOR temp
incr i : decr n
loop
if Ctx.Action = %DECRYPT then MakeDecryptKeySchedule Ctx
function = -1
END FUNCTION
'--------------------
MACRO FUNCTION imix(tt)
u = Ctx.@Td0[Ctx.@Se[byte3(tt)]]
u = u XOR Ctx.@Td1[Ctx.@Se[byte2(tt)]]
u = u XOR Ctx.@Td2[Ctx.@Se[byte1(tt)]]
u = u XOR Ctx.@Td3[Ctx.@Se[tt AND &hff]]
END MACRO = u
'====================
FUNCTION MakeDecryptKeySchedule(Ctx AS ENCRYPTION_CONTEXT)
LOCAL d&, e&, i&, retval&, t&, u&, k AS LONG PTR
k = Ctx.KD
d = 0 : e = Ctx.Rounds*4
@k[d] = Ctx.@KE[e] : @k[d+1] = Ctx.@KE[e+1]
@k[d+2] = Ctx.@KE[e+2] : @k[d+3] = Ctx.@KE[e+3]
d = d + 4 : e = e - 4
for i = 1 to Ctx.Rounds-1
t = Ctx.@KE[e] : @k[d] = imix(t)
t = Ctx.@KE[e+1] : @k[d+1] = imix(t)
t = Ctx.@KE[e+2] : @k[d+2] = imix(t)
t = Ctx.@KE[e+3] : @k[d+3] = imix(t)
d = d + 4 : e = e - 4
next i
@k[d] = Ctx.@KE[e] : @k[d+1] = Ctx.@KE[e+1]
@k[d+2] = Ctx.@KE[e+2] : @k[d+3] = Ctx.@KE[e+3]
END FUNCTION
'--------------------
MACRO FUNCTION packbytes(aa,bb,cc,dd)
aa = shiftlc(aa,24)
bb = shiftlc(bb,16)
cc = shiftlc(cc,8)
END MACRO = (aa OR bb OR cc OR dd)
'--------------------
MACRO FUNCTION enc_ta(aa,bb,cc,dd)
u = Ctx.@Te0[byte3(aa)]
u = u XOR Ctx.@Te1[byte2(bb)]
u = u XOR Ctx.@Te2[byte1(cc)]
u = u XOR Ctx.@Te3[dd AND &hff]
END MACRO = u
'--------------------
MACRO FUNCTION enc_tal(aa,bb,cc,dd,ww)
u = Ctx.@Se[byte3(aa)] : v = shiftrc(ww,24)
a0 = u XOR v
u = Ctx.@Se[byte2(bb)] : v = shiftrc(ww,16)
a1 = (u XOR v) AND &hff
u = Ctx.@Se[byte1(cc)] : v = shiftrc(ww,8)
a2 = (u XOR v) AND &hff
u = Ctx.@Se[dd AND &hff] : v = ww
a3 = (u XOR v) AND &hff
retval = packbytes(a0,a1,a2,a3)
END MACRO = retval
'====================
FUNCTION EncryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
LOCAL r&, t&, u&, v&, w&, pblock&, retval&, k AS LONG PTR
LOCAL a0&, a1&, a2&, a3&, t0&, t1&, t2&, t3&, s0&, s1&, s2&, s3&
pblock = Ctx.InBlock
t0 = get_block(pblock) : t1 = get_block(pblock)
t2 = get_block(pblock) : t3 = get_block(pblock)
k = Ctx.KE
t0 = t0 XOR @k[0] : t1 = t1 XOR @k[1]
t2 = t2 XOR @k[2] : t3 = t3 XOR @k[3]
for r = 1 to Ctx.Rounds-1
k = k + (4*4)
t = enc_ta(t0,t1,t2,t3) : a0 = t XOR @k[0]
t = enc_ta(t1,t2,t3,t0) : a1 = t XOR @k[1]
t = enc_ta(t2,t3,t0,t1) : a2 = t XOR @k[2]
t = enc_ta(t3,t0,t1,t2) : a3 = t XOR @k[3]
t0 = a0 : t1 = a1 : t2 = a2 : t3 = a3
next r
k = k + (4*4)
w = @k[0] : s0 = enc_tal(t0,t1,t2,t3,w)
w = @k[1] : s1 = enc_tal(t1,t2,t3,t0,w)
w = @k[2] : s2 = enc_tal(t2,t3,t0,t1,w)
w = @k[3] : s3 = enc_tal(t3,t0,t1,t2,w)
pblock = Ctx.OutBlock
put_block(pblock,s0) : put_block(pblock,s1)
put_block(pblock,s2) : put_block(pblock,s3)
END FUNCTION
'--------------------
MACRO FUNCTION dec_ta(aa,bb,cc,dd)
u = Ctx.@Td0[byte3(aa)]
u = u XOR Ctx.@Td1[byte2(bb)]
u = u XOR Ctx.@Td2[byte1(cc)]
u = u XOR Ctx.@Td3[dd AND &hff]
END MACRO = u
'--------------------
MACRO FUNCTION dec_tal(aa,bb,cc,dd,ww)
u = Ctx.@Sd[byte3(aa)] : v = shiftrc(ww,24)
a0 = u XOR v
u = Ctx.@Sd[byte2(bb)] : v = shiftrc(ww,16)
a1 = (u XOR v) AND &hff
u = Ctx.@Sd[byte1(cc)] : v = shiftrc(ww,8)
a2 = (u XOR v) AND &hff
u = Ctx.@Sd[dd AND &hff] : v = ww
a3 = (u XOR v) AND &hff
retval = packbytes(a0,a1,a2,a3)
END MACRO = retval
'====================
FUNCTION DecryptBlock&(Ctx AS ENCRYPTION_CONTEXT)
LOCAL r&, t&, u&, v&, w&, pblock&, retval&, k AS LONG PTR
LOCAL a0&, a1&, a2&, a3&, t0&, t1&, t2&, t3&, s0&, s1&, s2&, s3&
pblock = Ctx.InBlock
t0 = get_block(pblock) : t1 = get_block(pblock)
t2 = get_block(pblock) : t3 = get_block(pblock)
k = Ctx.KD
t0 = t0 XOR @k[0] : t1 = t1 XOR @k[1]
t2 = t2 XOR @k[2] : t3 = t3 XOR @k[3]
for r = 1 to Ctx.Rounds-1
k = k + (4*4)
t = dec_ta(t0,t3,t2,t1) : a0 = t XOR @k[0]
t = dec_ta(t1,t0,t3,t2) : a1 = t XOR @k[1]
t = dec_ta(t2,t1,t0,t3) : a2 = t XOR @k[2]
t = dec_ta(t3,t2,t1,t0) : a3 = t XOR @k[3]
t0 = a0 : t1 = a1 : t2 = a2 : t3 = a3
next r
k = k + (4*4)
w = @k[0] : s0 = dec_tal(t0,t3,t2,t1,w)
w = @k[1] : s1 = dec_tal(t1,t0,t3,t2,w)
w = @k[2] : s2 = dec_tal(t2,t1,t0,t3,w)
w = @k[3] : s3 = dec_tal(t3,t2,t1,t0,w)
pblock = Ctx.OutBlock
put_block(pblock,s0) : put_block(pblock,s1)
put_block(pblock,s2) : put_block(pblock,s3)
END FUNCTION
'====================
FUNCTION Rijndael_Init&(Ctx AS ENCRYPTION_CONTEXT)
STATIC table_buffer$
STATIC se AS BYTE PTR, te0 AS LONG PTR, te1 AS LONG PTR, te2 AS LONG PTR, te3 AS LONG PTR
STATIC sd AS BYTE PTR, td0 AS LONG PTR, td1 AS LONG PTR, td2 AS LONG PTR, td3 AS LONG PTR
STATIC rcon AS LONG PTR
Ctx.KE_Buffer = zbs(%SUBKEY_SIZE)
Ctx.KE = varptr(Ctx.KE_Buffer)
Ctx.KD_Buffer = zbs(%SUBKEY_SIZE)
Ctx.KD = varptr(Ctx.KD_Buffer)
if te0 = 0 then gosub MakeTables
Ctx.Se = se
Ctx.Sd = sd
Ctx.Te0 = te0
Ctx.Te1 = te1
Ctx.Te2 = te2
Ctx.Te3 = te3
Ctx.Td0 = td0
Ctx.Td1 = td1
Ctx.Td2 = td2
Ctx.Td3 = td3
Ctx.Rcon = rcon
exit function
'============
MakeTables:
LOCAL ss AS BYTE PTR
LOCAL root&, s1&, s2&, s3&, i1&, i2&, i4&, i8&, i9&, ib&, id&, ie&, t&, u&, v&, retval&
table_buffer$ = zbs((1024*8)+(256*2)+(40))
te0 = strptr(table_buffer)
te1 = (te0+1024) : te2 = te0+(1024*2) : te3 = te0+(1024*3)
td0 = te0+(1024*4) : td1 = te0+(1024*5) : td2 = te0+(1024*6) : td3 = te0+(1024*7)
se = te0+(1024*8) : sd = se+256 : rcon = se+(256*2)
root = &h11B
ss = codeptr(SS_Table)
for i1 = 0 to 255
s1 = @ss[i1]
s2 = shiftlc(s1,1)
if (s2 >= &h100) then s2 = s2 XOR root
s3 = s2 XOR s1
i2 = shiftlc(i1,1)
if (i2 >= &h100) then i2 = i2 XOR root
i4 = shiftlc(i2,1)
if (i4 >= &h100) then i4 = i4 XOR root
i8 = shiftlc(i4,1)
if (i8 >= &h100) then i8 = i8 XOR root
i9 = i8 XOR i1
ib = i9 XOR i2
id = i9 XOR i4
ie = i8 XOR i4 XOR i2
@se[i1] = s1 AND 255
u = shiftlc(s2,24)
v = shiftlc(s1,16)
t = u OR v
u = shiftlc(s1,8)
t = t OR u OR s3
@te0[i1] = t
u = shiftrc(t,8)
v = shiftlc(t,24)
@te1[i1] = u OR v
u = shiftrc(t,16)
v = shiftlc(t,16)
@te2[i1] = u OR v
u = shiftrc(t,24)
v = shiftlc(t,8)
@te3[i1] = u OR v
@sd[s1] = i1 AND 255
u = shiftlc(ie,24)
v = shiftlc(i9,16)
t = u OR v
u = shiftlc(id,8)
t = t OR u OR ib
@td0[s1] = t
u = shiftrc(t,8)
v = shiftlc(t,24)
@td1[s1] = u OR v
u = shiftrc(t,16)
v = shiftlc(t,16)
@td2[s1] = u OR v
u = shiftrc(t,24)
v = shiftlc(t,8)
@td3[s1] = u OR v
next i1
LOCAL i&, r&
r = 1
@rcon[0] = shiftlc(r,24)
for i = 1 to 9
r = shiftlc(r,1)
if (r >= &h100) then r = r XOR ROOT
@rcon[i] = shiftlc(r,24)
next i
RETURN
SS_Table:
! DD &h7b777c63, &hc56f6bf2, &h2b670130, &h76abd7fe
! DD &h7dc982ca, &hf04759fa, &hafa2d4ad, &hc072a49c
! DD &h2693fdb7, &hccf73f36, &hf1e5a534, &h1531d871
! DD &hc323c704, &h9a059618, &he2801207, &h75b227eb
! DD &h1a2c8309, &ha05a6e1b, &hb3d63b52, &h842fe329
! DD &hed00d153, &h5bb1fc20, &h39becb6a, &hcf584c4a
! DD &hfbaaefd0, &h85334d43, &h7f02f945, &ha89f3c50
! DD &h8f40a351, &hf5389d92, &h21dab6bc, &hd2f3ff10
! DD &hec130ccd, &h1744975f, &h3d7ea7c4, &h73195d64
! DD &hdc4f8160, &h88902a22, &h14b8ee46, &hdb0b5ede
! DD &h0a3a32e0, &h5c240649, &h62acd3c2, &h79e49591
! DD &h6d37c8e7, &ha94ed58d, &heaf4566c, &h08ae7a65
! DD &h2e2578ba, &hc6b4a61c, &h1f74dde8, &h8a8bbd4b
! DD &h66b53e70, &h0ef60348, &hb9573561, &h9e1dc186
! DD &h1198f8e1, &h948ed969, &he9871e9b, &hdf2855ce
! DD &h0d89a18c, &h6842e6bf, &h0f2d9941, &h16bb54b0
END FUNCTION
'-- end RIJNDAEL.BAS
'#########################################################################
'-- TESTBED.BAS
'=====================================================================
' Rijndael 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 RIJNDAEL.BAS
#INCLUDE "RIJNDAEL.BAS"
DECLARE FUNCTION Hex2Show$(Buffer$)
'====================
FUNCTION PBMain&()
REGISTER i&
LOCAL key$, plain$, cipher$, shouldbe$, t$
LOCAL ctx AS ENCRYPTION_CONTEXT ' defined in RIJNDAEL.BAS
EnterCC
'-- Standard Rijndael test vectors (from ECB_TBL.TXT, I=1)
'-- 256-bit key
key = chr$(&h00,&h01,&h02,&h03,&h05,&h06,&h07,&h08,&h0A,&h0B,&h0C,&h0D,&h0F,&h10,&h11,&h12, _
&h14,&h15,&h16,&h17,&h19,&h1A,&h1B,&h1C,&h1E,&h1F,&h20,&h21,&h23,&h24,&h25,&h26)
plain = chr$(&h83,&h4E,&hAD,&hFC,&hCA,&hC7,&hE1,&hB3,&h06,&h64,&hB1,&hAB,&hA4,&h48,&h15,&hAB)
cipher = zbs(len(plain))
shouldbe = chr$(&h19,&h46,&hDA,&hBF,&h6A,&h03,&hA2,&hA2,&hC3,&hD0,&hB0,&h50,&h80,&hAE,&hD6,&hFC)
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$(&h00,&h01,&h02,&h03,&h05,&h06,&h07,&h08,&h0A,&h0B,&h0C,&h0D,&h0F,&h10,&h11,&h12, _
&h14,&h15,&h16,&h17,&h19,&h1A,&h1B,&h1C,&h1E,&h1F,&h20,&h21,&h23,&h24,&h25,&h26)
gosub DoDecrypt
t = t + "plain: " + Hex2Show$(plain) + eol + eol
'-- 192-bit key
key = chr$(&h00,&h01,&h02,&h03,&h05,&h06,&h07,&h08,&h0A,&h0B,&h0C,&h0D,&h0F,&h10,&h11,&h12, _
&h14,&h15,&h16,&h17,&h19,&h1A,&h1B,&h1C)
plain = chr$(&h2D,&h33,&hEE,&hF2,&hC0,&h43,&h0A,&h8A,&h9E,&hBF,&h45,&hE8,&h09,&hC4,&h0B,&hB6)
cipher = zbs(len(plain))
shouldbe = chr$(&hDF,&hF4,&h94,&h5E,&h03,&h36,&hDF,&h4C,&h1C,&h56,&hBC,&h70,&h0E,&hFF,&h83,&h7F)
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$(&h00,&h01,&h02,&h03,&h05,&h06,&h07,&h08,&h0A,&h0B,&h0C,&h0D,&h0F,&h10,&h11,&h12, _
&h14,&h15,&h16,&h17,&h19,&h1A,&h1B,&h1C)
gosub DoDecrypt
t = t + "plain: " + Hex2Show$(plain) + eol + eol
'-- 128-bit key
key$ = chr$(&h00,&h01,&h02,&h03,&h05,&h06,&h07,&h08,&h0A,&h0B,&h0C,&h0D,&h0F,&h10,&h11,&h12)
plain = chr$(&h50,&h68,&h12,&hA4,&h5F,&h08,&hC8,&h89,&hB9,&h7F,&h59,&h80,&h03,&h8B,&h83,&h59)
cipher = zbs(len(plain))
shouldbe = chr$(&hD8,&hF5,&h32,&h53,&h82,&h89,&hEF,&h7D,&h06,&hB5,&h06,&hA4,&hFD,&h5B,&hE9,&hC9)
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$(&h00,&h01,&h02,&h03,&h05,&h06,&h07,&h08,&h0A,&h0B,&h0C,&h0D,&h0F,&h10,&h11,&h12)
gosub DoDecrypt
t = t + "plain: " + Hex2Show$(plain) + eol + eol
mbox(t)
ExitCC
exit function
'============
DoEncrypt:
ctx.action = %ENCRYPT
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 16) = 0
EncryptBlock ctx
ctx.InBlock = ctx.InBlock + %BLOCKSIZE
ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
next i&
else
mbox("DoEncrypt SetKey Error")
end if
'-- Burn the subkey
if Ctx.KE then poke$ Ctx.KE, zbs(sizeof(Ctx.KE_Buffer))
if Ctx.KD then poke$ Ctx.KD, zbs(sizeof(Ctx.KD_Buffer))
RETURN
'============
DoDecrypt:
ctx.action = %DECRYPT
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 16) = 0
DecryptBlock ctx
ctx.InBlock = ctx.InBlock + %BLOCKSIZE
ctx.OutBlock = ctx.OutBlock + %BLOCKSIZE
next i
else
mbox("DoDecrypt SetKey Error")
end if
'-- Burn the subkey
if Ctx.KE then poke$ Ctx.KE, zbs(sizeof(Ctx.KE_Buffer))
if Ctx.KD then poke$ Ctx.KD, zbs(sizeof(Ctx.KD_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