CryptRandomData() Odd behavior

Just starting out? Need help? Post your questions and find answers here.
User avatar
JackWebb
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Dec 16, 2009 1:42 pm
Location: Tampa Florida

CryptRandomData() Odd behavior

Post by JackWebb »

Hello all!

Not sure if this is a coding question or not. I have been working on some encryption routines for a password manager. While stress testing the routines on different machines, I ran into a problem on an old Windows 7 HP desktop. My other two machines are a Windows 10 all in one touch screen desktop, and a Windows 11 Laptop. All three are 64 bit machines. On the Windows 7 machine, Debug Len(Initvector$) returns semi random numbers ranging from 2 to 16 inside the test code, the other two machines consistently return 8.. What's even stranger is the the code below (taken exactly as you see it from the test code) always return 13 when run by itself on the windows 7 machine, but always 8 on the other two no matter what. Not sure what's going on here. Is this a hardware issue, a windows 7 issue? Using PB630 final on all machines.

Code: Select all

*InitVector = AllocateMemory(16)
OpenCryptRandom()
Repeat
  CryptRandomData(*InitVector, 16)
  InitVector$ = PeekS(*InitVector, 16)
  Debug Len(Initvector$)
ForEver
CloseCryptRandom()
Make everything as simple as possible, but not simpler. ~Albert Einstein
SMaag
Enthusiast
Enthusiast
Posts: 385
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: CryptRandomData() Odd behavior

Post by SMaag »

InitVector$ = PeekS(*InitVector, 16)
Debug Len(Initvector$)
As I remember you can not Peek an encrypted string because encryption may generate '0' within the String.
breeze4me
Enthusiast
Enthusiast
Posts: 672
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: CryptRandomData() Odd behavior

Post by breeze4me »

As SMaag's comment pointed out, it's problematic because it may contain invalid character values, and the number of characters read in your code is also incorrect.
However, rather than using PeekS directly, it is recommended to verify that each byte of the data generated by the CryptRandomData function falls within the valid character range.

Code: Select all

*InitVector = AllocateMemory(16)
OpenCryptRandom()
Repeat
  CryptRandomData(*InitVector, 16)
  ;InitVector$ = PeekS(*InitVector, 16, #PB_Ascii)
  ; or
  InitVector$ = PeekS(*InitVector, 8) ;The #PB_Unicode flag is the default, as it treats each character as 2 bytes.
  Debug Len(Initvector$)
ForEver
CloseCryptRandom()
User avatar
NicTheQuick
Addict
Addict
Posts: 1582
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: CryptRandomData() Odd behavior

Post by NicTheQuick »

Don't store binary data in a string. It's that simple.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
JackWebb
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Dec 16, 2009 1:42 pm
Location: Tampa Florida

Re: CryptRandomData() Odd behavior

Post by JackWebb »

breeze4me wrote: Sat Feb 07, 2026 1:32 pm However, rather than using PeekS directly, it is recommended to verify that each byte of the data generated by the CryptRandomData function falls within the valid character range.
Yes good point. I suspect that there maybe a character issue, but what are the invalid characters? It still doesn't answer the question as to why string length is always 8 on 2 machines no matter what, and on the other machine it is unpredictable unless the code runs alone, but in that case it's always 13.
Make everything as simple as possible, but not simpler. ~Albert Einstein
User avatar
JackWebb
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Dec 16, 2009 1:42 pm
Location: Tampa Florida

Re: CryptRandomData() Odd behavior

Post by JackWebb »

SMaag wrote: Sat Feb 07, 2026 6:05 am As I remember you can not Peek an encrypted string because encryption may generate '0' within the String.
That is true and Chr(0) is filtered out, but I suspect there could be other characters that are problematic, but which ones?

Code: Select all

*InitVector = AllocateMemory(16)
OpenCryptRandom()
Repeat
  CryptRandomData(*InitVector, 16)
  InitVector$ = PeekS(*InitVector, 16)
  Debug Len(Initvector$)
Until Len(Initvector$) > 7 And Not FindString(InitVector$, Chr(0))
CloseCryptRandom()
Make everything as simple as possible, but not simpler. ~Albert Einstein
User avatar
STARGÅTE
Addict
Addict
Posts: 2305
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: CryptRandomData() Odd behavior

Post by STARGÅTE »

JackWebb wrote: Sat Feb 07, 2026 4:45 pm
breeze4me wrote: Sat Feb 07, 2026 1:32 pm However, rather than using PeekS directly, it is recommended to verify that each byte of the data generated by the CryptRandomData function falls within the valid character range.
Yes good point. I suspect that there maybe a character issue, but what are the invalid characters? It still doesn't answer the question as to why string length is always 8 on 2 machines no matter what, and on the other machine it is unpredictable unless the code runs alone, but in that case it's always 13.
It makes no sense to talk about a problem that only arises because the programmer uses the functions incorrectly.
With AllocateMemory(16) you create a memory with 16 bytes. With PeekS(*InitVector, 16) you try to read a string with 16 characters, which are by default string format 32 bytes.
This means, you read beyond the reserved memory, which gives unpredictable results, dependent how the operating system managed the reserved memory (not PureBasic).
Further, depending on the crypt algorithm used on the operation system (e.g. Microsoft Cryptography API) it produces more or less the byte sequence 00'00 (NUL-character in unicode), leading to an early stop for PeekS() and leading to a shorter result in Len().

Further, you can't search for the NUL-Character.
More garbage code. Please stop.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
NicTheQuick
Addict
Addict
Posts: 1582
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: CryptRandomData() Odd behavior

Post by NicTheQuick »

Why do you still try to read binary data as a Unicode string?
UCS-2 does not allow 2^16-1 characters. It's less than that and you have to read the specification for it. Here's a start point: https://en.wikipedia.org/wiki/UTF-16

But why would you wanna do that? Do you really need Chinese and Cyrillic characters, emojis and control characters in your string?
Better define a table of valid characters and use the random generator to choose the characters randomly.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
infratec
Always Here
Always Here
Posts: 7804
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: CryptRandomData() Odd behavior

Post by infratec »

JackWebb wrote: Sat Feb 07, 2026 4:45 pm It still doesn't answer the question as to why string length is always 8 on 2 machines no matter what, and on the other machine it is unpredictable unless the code runs alone, but in that case it's always 13.
Use ShowMemoryViewer() to see what happens.

But this is only informational, as already written: you can not use PeekS()

You can use Base64Encoder()
Last edited by infratec on Sat Feb 07, 2026 5:26 pm, edited 1 time in total.
User avatar
JackWebb
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Dec 16, 2009 1:42 pm
Location: Tampa Florida

Re: CryptRandomData() Odd behavior

Post by JackWebb »

STARGÅTE wrote: Sat Feb 07, 2026 5:04 pm It makes no sense to talk about a problem that only arises because the programmer uses the functions incorrectly.
With AllocateMemory(16) you create a memory with 16 bytes. With PeekS(*InitVector, 16) you try to read a string with 16 characters, which are by default string format 32 bytes.
This means, you read beyond the reserved memory, which gives unpredictable results, dependent how the operating system managed the reserved memory

Further, you can't search for the NUL-Character.
And the winner is Stargate! Thank you for that, and now they all work the same, and now it makes sense.
Further, you can't search for the NUL-Character.
Yes that's correct, dumb mistakes. Funny thing is I stress tested for 12 hours, 3.5 million iterations without an error. I stopped the test.
Last edited by JackWebb on Sat Feb 07, 2026 5:57 pm, edited 2 times in total.
Make everything as simple as possible, but not simpler. ~Albert Einstein
User avatar
JackWebb
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Dec 16, 2009 1:42 pm
Location: Tampa Florida

Re: CryptRandomData() Odd behavior

Post by JackWebb »

infratec wrote: Sat Feb 07, 2026 5:24 pm
Use ShowMemoryViewer() to see what happens.

But this is only informational, as already written: you can not use PeekS()

You can use Base64Encoder()
Thank you! I will have to test for that now that Stargate has pointed out my error. Interesting. So base64 encode the InitString$ before it is used.. I'll have to try that as well. Back to testing with the changes.
Make everything as simple as possible, but not simpler. ~Albert Einstein
User avatar
JackWebb
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Dec 16, 2009 1:42 pm
Location: Tampa Florida

Re: CryptRandomData() Odd behavior

Post by JackWebb »

NicTheQuick wrote: Sat Feb 07, 2026 5:08 pm Why do you still try to read binary data as a Unicode string?
UCS-2 does not allow 2^16-1 characters. It's less than that and you have to read the specification for it. Here's a start point: https://en.wikipedia.org/wiki/UTF-16

But why would you wanna do that? Do you really need Chinese and Cyrillic characters, emojis and control characters in your string?
Nick, thank you for the reply! I have found your excellent encryption routines in the forum, you understand this stuff better than almost anyone. I am using base64 encoding for my strings The above routine is only to produce the initvector. Infratec has an idea that I should base64 encode the initstring. I'll have to go make some changes to see if that can work. Your input is much appreciated!
Better define a table of valid characters and use the random generator to choose the characters randomly.
Now there's an idea.
Make everything as simple as possible, but not simpler. ~Albert Einstein
Post Reply