Page 1 of 1
CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 2:52 am
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()
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 6:05 am
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.
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 1:32 pm
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()
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 3:46 pm
by NicTheQuick
Don't store binary data in a string. It's that simple.
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 4:45 pm
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.
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 4:58 pm
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()
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 5:04 pm
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.
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 5:08 pm
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.
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 5:24 pm
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()
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 5:25 pm
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.
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 5:30 pm
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.
Re: CryptRandomData() Odd behavior
Posted: Sat Feb 07, 2026 5:39 pm
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.