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

Random (One Time) Pad Generator

Algorithm creator(s)

n/a


PB author(s)

Steve Hutchesson


Description

Create a One Time Pad (OTP). Implemented in PB's inline assembler.


Note

Ported from the MASM version to PB. Included is John Walker's public domain random testing application ENT to test the quality of the results.


Source

https://forum.powerbasic.com/forum/user-to-user-discussions/programming/755535-otp-one-time-pad-comments?p=755547#post755547


See also


Source Code

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

' ��������������������������������������������������������������������������������������������������

    MACRO FUNCTION malloc(bcnt) = GlobalAlloc(%GMEM_FIXED or %GMEM_ZEROINIT,bcnt)
    MACRO FUNCTION mfree(hMem) = GlobalFree(hMem)

' ��������������������������������������������������������������������������������������������������

FUNCTION random_pad$(ByVal psiz as DWORD)

  ' ---------------------------------------------
  ' shift from 4 gig range to 4 gig ^ 4 gig range
  ' ---------------------------------------------
    LOCAL pad1 as DWORD
    LOCAL pad2 as DWORD

    rpad1$ = get_pad$(psiz)             ' get the 1st pad
    pad1 = StrPtr(rpad1$)

  ' -------------------------------------------------
  ' This combined delay ensures that the two pads use
  ' very different seeds that are not predictable.
  ' -------------------------------------------------
    ! cpuid                             ; serialising instruction
    ! pause                             ; spinlock delay instruction

    SleepEx 20,0                        ' yield at least 1 timeslice

    ! cpuid                             ; serialising instruction
    ! pause                             ; spinlock delay instruction
  ' ------------------------------------

    rpad2$ = get_pad$(psiz)             ' get the second pad
    pad2 = StrPtr(rpad2$)

  ' -------------------------
  ' XOR the two pads together
  ' -------------------------
    ! mov esi, pad1
    ! mov edi, pad2
    ! mov ebx, psiz
    ! xor ecx, ecx
  lbl1:
    ! movzx eax, BYTE PTR [esi+ecx]
    ! movzx edx, BYTE PTR [edi+ecx]
    ! xor al, dl
    ! mov [esi+ecx], al                 ; write result back to 1st pad
    ! add ecx, 1
    ! sub ebx, 1
    ! jnz lbl1
  ' -------------------------

    FUNCTION = rpad1$

End FUNCTION

' ��������������������������������������������������������������������������������������������������

FUNCTION get_pad$(ByVal psiz as DWORD)

    LOCAL mptr as DWORD             ' memory pointer
    LOCAL ppad as DWORD             ' basic string pointer

    mptr = create_random_pad(psiz)  ' mptr is the address of the random pad
    pad$ = space$(psiz)             ' create a basic string
    ppad = StrPtr(pad$)             ' get its address
    copymem(mptr,ppad,psiz)         ' copy the allocated memory to the basic string
    mfree(mptr)                     ' release memory

    FUNCTION = pad$

End FUNCTION

' ��������������������������������������������������������������������������������������������������

FUNCTION create_random_pad(ByVal bcnt as DWORD) as DWORD

    #REGISTER NONE

    LOCAL range as DWORD
    LOCAL pmem  as DWORD
    LOCAL xtra  as DWORD
    LOCAL rseed as DWORD
    LOCAL icnt  as DWORD
    LOCAL lcnt  as DWORD

  PREFIX "!"

    mov eax, bcnt
    add eax, eax                    ; double the original count
    mov lcnt, eax                   ; store result in lcnt

    mov range, 255                  ; byte range

    END PREFIX
      pmem = malloc(lcnt)
    PREFIX "!"

    call get_random_seed            ; get an initial seed
    mov rseed, eax

    xor ebx, ebx                    ; set the loop lcnter
    mov edi, pmem                   ; put the buffer address into EDI

; ------------------
; NaN's nrandom algo
; ------------------
  lpstart:
    mov eax, rseed
    test eax, &H80000000
    jz  lbl1
    add eax, &H7FFFFFFF
  lbl1:   
    xor edx, edx
    mov ecx, 127773
    div ecx
    mov ecx, eax
    mov eax, 16807
    mul edx
    mov edx, ecx
    mov ecx, eax
    mov eax, 2836
    mul edx
    sub ecx, eax
    xor edx, edx
    mov eax, ecx
    mov rseed, ecx
    div range

    mov [edi], dl                   ; write BYTE result to buffer
    add edi, 1

    add rseed, 1

    add icnt, 1
    add ebx, 1
    cmp ebx, lcnt
    jl lpstart

; --------------------------------------------------------------------------------------------------

    END PREFIX
      xtra = malloc(bcnt)           ' allocate a buffer for the pad size
    PREFIX "!"

    mov esi, pmem                   ; loaded random buffer
    mov edi, xtra
    mov ebx, bcnt
    sub esi, 1
    mov edx, ebx
    neg edx

  cploop:
    add esi, 1
    movzx eax, BYTE PTR [esi]
    movzx ecx, BYTE PTR [esi+ebx]
    xor eax, ecx
    mov [edi], al
    add edi, 1
    add edx, 1
    jnz cploop

  END PREFIX

    mfree(pmem)

    FUNCTION = xtra

End FUNCTION

' ��������������������������������������������������������������������������������������������������

FUNCTION get_random_seed() as DWORD
  ' ------------------------------------------------------------
  ' get 2 random seeds from 2 spaced calls and XOR them together
  ' ------------------------------------------------------------
    #REGISTER NONE

    LOCAL seed1 as DWORD
    LOCAL seed2 as DWORD

    seed1 = create_random_seed()

    ! cpuid                             ; serialising instruction
    ! pause                             ; spinlock delay instruction

    SleepEx 20,0                        ' yield at least 1 timeslice

    ! cpuid                             ; serialising instruction
    ! pause                             ; spinlock delay instruction

    seed2 = create_random_seed()

    ! mov eax, seed1
    ! mov ecx, seed2
    ! xor eax, ecx

    ! mov FUNCTION, eax

End FUNCTION

' ��������������������������������������������������������������������������������������������������

FUNCTION create_random_seed() as DWORD

  ' The STRING technique converts the output to a string, reverses the string
  ' then read up to 10 characters from the left side of the string which
  ' is then converted back to a DWORD value.

  ' the string is reversed to get the most rapidly changing numbers that
  ' are normally on the right side of the converted number.

  ' get DWORD output from both RDTSC and GetTickCount(), bit rotate both
  ' values by the WORD value taken from the two leading bytes (range 0-99),
  ' 1 left, the other right then XOR the results together for the output.

    #REGISTER NONE

    LOCAL seed as DWORD
    LOCAL shft as DWORD
    LOCAL rdts as DWORD
    LOCAL tcnt as DWORD
    LOCAL see2 as DWORD
    LOCAL tcn$

    ! rdtsc
    ! mov rdts, eax                     ' use the low DWORD from RDTSC

    tcn$ = strreverse$(format$(rdts))
    shft = val(left$(tcn$,2))           ' get shift range 0-99
    seed = val(left$(tcn$,10))          ' read up to 10 characters from the string

    tcnt = val(left$(strreverse$(format$(GetTickCount)),10))

    ! mov ecx, shft
    ! ror tcnt, cl                      ; rotate tcnt right by shft
    ! mov ecx, shft
    ! rol seed, cl                      ; rotate seed left by shft

    ! mov eax, seed
    ! mov ecx, tcnt
    ! xor eax, ecx
    ! mov seed, eax

    FUNCTION = seed

End FUNCTION

' ��������������������������������������������������������������������������������������������������

FUNCTION copymem(ByVal src as DWORD,ByVal dst as DWORD,ByVal ln as DWORD) as DWORD

  PREFIX "!"
    cld
    mov esi, src
    mov edi, dst
    mov ecx, ln

    shr ecx, 2
    rep movsd

    mov ecx, ln
    and ecx, 3
    rep movsb
  END PREFIX

End FUNCTION

' ��������������������������������������������������������������������������������������������������

FUNCTION exist(fname$) as DWORD
  FUNCTION = Len( Dir$(fname$, 17) ) > 0
END FUNCTION

' ��������������������������������������������������������������������������������������������������

FUNCTION app_path() as STRING

    #REGISTER NONE

    LOCAL sln as DWORD
    LOCAL pst as DWORD

    buf$ = nul$(260)
    pst = StrPtr(buf$)

    sln = GetModuleFileName(ByVal %NULL,ByVal pst,260)

    PREFIX "! "
    mov esi, pst                ; load the buffer address
    add esi, sln                ; add length to locate at end of result string
    mov edi, esi                ; store esi in edi
  ; -----------------------
  ; backscan to get 1st "\"
  ; -----------------------
  lbl1:
    sub esi, 1
    movzx eax, BYTE PTR [esi]   ; zero extend byte
    cmp eax, "\"                ; test for "\"
    jne lbl1                    ; loop back if not

    sub edi, esi
    sub sln, edi
    add sln, 1
    END PREFIX

    FUNCTION = left$(buf$,sln)

End FUNCTION

' ��������������������������������������������������������������������������������������������������

Mirror provided by Knuth Konrad