Page 1 of 1

Deriving key and vector for AES-256

Posted: Mon Dec 18, 2023 6:07 pm
by Catdaddy
Hello,

I am attempting to use AESEncryption in Purebasic. I want to be able to encrypt/decrypt strings with AES-256. I am using #PB_Cipher_CBC so I need to have a 32bit key and 16bit vector. In my code I am deriving the key and vector bytes from the fingerprint (SHA3) of a given string. I chop up the first 64 bytes of the fingerprint into 32 pairs of Hex strings which the value of are poked into a memory buffer to be read as the Key. Likewise, the last 32 bytes of the fingerprint are chopped up into 16 pairs of Hex strings which the value of each are poked into a memory buffer to be read as the Vector.

If you run my code you'll see that the bytes that are poked into the memory buffers (for the key and vector) are not what is being peeked from each buffer. When I point AESEncoder to the key and vector buffers I don't believe the values are correct.

Not sure if I'm explaining this correctly but if anyone could lend a hand I would be extremely grateful. Thank you.

Code: Select all

UseSHA3Fingerprint()

Procedure DeriveKey(Password.s, *Key, *InitVect)
	Fingerprint.s = StringFingerprint(Password, #PB_Cipher_SHA3, 512)

	Key.s = Left(Fingerprint, 64)
	InitVect.s = Right(Fingerprint, 32)

	Debug "FingerPrint: " + Fingerprint
	Debug "Key String: " + Key
	Debug "Vect String: " + InitVect		

	;Key
	Counter.b = 0
	Debug ""
	Debug "Key"
	Debug "==="
	For C = 1 To 64 Step 2
		ByteString.s = "$" + Mid(Key, C, 2)
		Debug ByteString + " = " + Val(ByteString)
		PokeB(*Key + Counter, Val(ByteString))
		Counter+1
	Next

	;InitVect
	Counter.b = 0
	Debug ""
	Debug "InitVect"
	Debug "========"
	For C = 1 To 32 Step 2
		ByteString.s = "$" + Mid(InitVect, C, 2)
		Debug ByteString + " = " + Val(ByteString)
		PokeB(*InitVect + Counter, Val(ByteString))
		Counter+1
	Next
EndProcedure


*Key = AllocateMemory(32)
*InitVect = AllocateMemory(16)

DeriveKey("iamjustarandomstring", *Key, *InitVect)

Debug ""
Debug "Peeked key"
Debug "========"
 
For C = 0 To 31
	Debug PeekB(*Key + C)
Next


Debug ""
Debug "Peeked vect"
Debug "========"
 
For C = 0 To 15
	Debug PeekB(*InitVect + C)
Next

Re: Deriving key and vector for AES-256

Posted: Mon Dec 18, 2023 7:13 pm
by spikey
You are overflowing the byte type numeric limit. It's a signed type and supports values between -128 and +127. Anything larger than +127 poked into a memory address will be interpreted as a negative when read back with PeekB because it has the sign bit set. If you read back with PeekA it should look more like what you're expecting to see (because the A type is unsigned).

Re: Deriving key and vector for AES-256

Posted: Mon Dec 18, 2023 7:22 pm
by Mijikai
Like this ?

Code: Select all

EnableExplicit

UseSHA3Fingerprint()

Procedure.i DeriveKey(Password.s)
  Protected *key
  Protected sha.s
  *key = AllocateMemory(48)
  If *key
    sha = StringFingerprint(Password,#PB_Cipher_SHA3,512)
    CopyMemory(@sha,*key,32)
    CopyMemory(@sha + StringByteLength(sha) - 16,*key + 32,16)
    Debug sha
  EndIf
  ProcedureReturn *key
EndProcedure

Procedure.i Main()
  Protected *key
  Protected *vec
  *key = DeriveKey("iamjustarandomstring")
  *vec = *key + 32
  Debug PeekS(*key,16)
  Debug PeekS(*vec,8)
  ProcedureReturn #Null
EndProcedure

End Main()

Re: Deriving key and vector for AES-256

Posted: Mon Dec 18, 2023 8:03 pm
by Catdaddy
spikey wrote: Mon Dec 18, 2023 7:13 pm You are overflowing the byte type numeric limit. It's a signed type and supports values between -128 and +127. Anything larger than +127 poked into a memory address will be interpreted as a negative when read back with PeekB because it has the sign bit set. If you read back with PeekA it should look more like what you're expecting to see (because the A type is unsigned).
:oops: You are absolutely correct. Forgive me, I'm still getting used to PureBasic types. Still got a ways to go :)

Re: Deriving key and vector for AES-256

Posted: Mon Dec 18, 2023 8:07 pm
by Catdaddy
Mijikai wrote: Mon Dec 18, 2023 7:22 pm Like this ?

Code: Select all

EnableExplicit

UseSHA3Fingerprint()

Procedure.i DeriveKey(Password.s)
  Protected *key
  Protected sha.s
  *key = AllocateMemory(48)
  If *key
    sha = StringFingerprint(Password,#PB_Cipher_SHA3,512)
    CopyMemory(@sha,*key,32)
    CopyMemory(@sha + StringByteLength(sha) - 16,*key + 32,16)
    Debug sha
  EndIf
  ProcedureReturn *key
EndProcedure

Procedure.i Main()
  Protected *key
  Protected *vec
  *key = DeriveKey("iamjustarandomstring")
  *vec = *key + 32
  Debug PeekS(*key,16)
  Debug PeekS(*vec,8)
  ProcedureReturn #Null
EndProcedure

End Main()
This is MUCH more elegant than my code. Thank you, Mijikai. You can probably tell I'm just getting my feet wet with pointers and working directly with memory.

Re: Deriving key and vector for AES-256

Posted: Tue Dec 19, 2023 4:54 pm
by Catdaddy
OK. Forgive me for being a pain, but how can I expose a pointer to a procedure? I slightly modified the example listing for AESEncoder() (see below). Whenever I run this I get a specified buffer is 0 error. I thought "Shared" gave the procedure access to the variable (*Key and *Vec). Does this not work with pointers? Sorry for being dense.

Code: Select all

UseSHA3Fingerprint()

Procedure.s CryptString(String.s, Action.i)
	Shared *Key
	Shared *Vec

	StringMemorySize = StringByteLength(String) + SizeOf(Character)
	*CipheredString = AllocateMemory(StringMemorySize)   
	*DecipheredString = AllocateMemory(StringMemorySize) 
	
	If Action = 1
		AESEncoder(@String$, *CipheredString, StringByteLength(String), *Key, 256, *Vec)
		ProcedureReturn PeekS(*CipheredString)
	EndIf

	If Action = 0
		AESDecoder(*CipheredString, *DecipheredString, StringByteLength(String), *Key, 256, *Vec)
		ProcedureReturn PeekS(*DecipheredString)
	EndIf
EndProcedure

*Key = AllocateMemory(64)
*Vec = AllocateMemory(32)
Password.s = "iamjustarandomstring"
Fingerprint.s = StringFingerprint(Password, #PB_Cipher_SHA3, 512)
CopyMemory(@Fingerprint,*Key,64)
CopyMemory(@Fingerprint + StringByteLength(Fingerprint) - 64,*Vec,32)

Debug "Key: " + PeekS(*Key,32)
Debug "Vector: " + PeekS(*Vec,16)

Debug CryptString("password", 1)

Re: Deriving key and vector for AES-256

Posted: Tue Dec 19, 2023 5:01 pm
by spikey
String$ <> String.s, see line 12. These are two separate variables in PB.

I'd strongly advise the use of the EnableExplicit directive which will trap this sort of typo.

Re: Deriving key and vector for AES-256

Posted: Tue Dec 19, 2023 5:30 pm
by Catdaddy
spikey wrote: Tue Dec 19, 2023 5:01 pm String$ <> String.s, see line 12. These are two separate variables in PB.

I'd strongly advise the use of the EnableExplicit directive which will trap this sort of typo.
Thank you, Spikey. That's what I get for being in a rush. Happy Holidays!

Re: Deriving key and vector for AES-256

Posted: Tue Dec 19, 2023 5:33 pm
by spikey
Catdaddy wrote: Tue Dec 19, 2023 5:30 pm Happy Holidays!
And to you! :D

Re: Deriving key and vector for AES-256

Posted: Sat Dec 23, 2023 2:45 pm
by freak
The DeriveCypherKey() function in the new 6.10 beta release is designed for this. An example can be found here: https://www.purebasic.fr/english/viewto ... 71#p613171

Re: Deriving key and vector for AES-256

Posted: Sat Dec 23, 2023 3:09 pm
by Catdaddy
freak wrote: Sat Dec 23, 2023 2:45 pm The DeriveCypherKey() function in the new 6.10 beta release is designed for this. An example can be found here: https://www.purebasic.fr/english/viewto ... 71#p613171
Whoa!!! Christmas came early this year :D Thank you, Freak. I'm definitely going to try the beta. Merry Christmas!