Page 1 of 1

RSA crypto with Windows CSP

Posted: Mon May 15, 2017 9:30 pm
by tj1010
CSP is the only out-of-the-box solution for RSA on Windows. I've searched and seen a lot of threads on CSP here but the few using RSA were basically quick demos of encrypting and decryption using CSP storage and little configuration and none of them actually exported keys.

From what I've read on MSDN my code actually generates the key pairs and exports them, but I've yet to get the encryption to use these external keys. Has anyone had any luck saving keys outside of the CSP container and using them later?

I wrote this in a couple days worth of spare time using MSDN. It should be working I just haven't seen any CSP based demos of exporting keys. According to MSDN this should be working. You should be able to Base64 rsa\pub and share it and decrypt with rsa\priv.

Code: Select all

#PROV_RSA_FULL = 1
#CRYPT_NEWKEYSET = 8
#CRYPT_DELETEKEYSET = 16
#CRYPT_EXPORTABLE = 1
#CALG_RSA_KEYX = 41984
#MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0"
#MS_STRONG_PROV = "Microsoft Strong Cryptographic Provider"
#MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0"
#CRYPT_VERIFYCONTEXT = -268435456
#PUBLICKEYBLOB   =    $06;
#PRIVATEKEYBLOB   =   $07;
#PLANTEXTKEYBLOB   =   $08;
#OPAQUEKEYBLOB   =   $09  ;
#CRYPT_EXPORTABLE = 1


Structure mykeys
  *priv
  *pub
  keysize.l
EndStructure
Global rsa.mykeys
rsa\priv=AllocateMemory(4096)
rsa\pub=AllocateMemory(4096)

Procedure encrypt(*mem,length,*key)
  If CryptAcquireContext_(@hProv, #Null, #MS_STRONG_PROV, #PROV_RSA_FULL, #CRYPT_VERIFYCONTEXT) = 0
    CryptAcquireContext_(@hProv, #Null, #MS_STRONG_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET|#CRYPT_VERIFYCONTEXT)
  EndIf
  If CryptImportKey_(hProv,*key,rsa\keysize,0,0,@hKey)
    CryptEncrypt_(hKey,0,1,$40,*mem,@length,rsa\keysize)
    CryptDestroyKey_(hKey)
  EndIf
  If hProv : CryptReleaseContext_(hProv,0) : EndIf
EndProcedure

Procedure decrypt(*mem,length,*key)
  If CryptAcquireContext_(@hProv, #Null, #MS_STRONG_PROV, #PROV_RSA_FULL, #CRYPT_VERIFYCONTEXT) = 0
    CryptAcquireContext_(@hProv, #Null, #MS_STRONG_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET|#CRYPT_VERIFYCONTEXT)
  EndIf
  If CryptImportKey_(hProv,*key,rsa\keysize,0,0,@hKey)
    CryptDecrypt_(hKey,0,1,$40,*mem,rsa\keysize)
    CryptDestroyKey_(hKey)
  EndIf
If hProv : CryptReleaseContext_(hProv,0) : EndIf
EndProcedure

Procedure makekeys(*private,*public)
  If CryptAcquireContext_(@hProv, #Null, #MS_STRONG_PROV, #PROV_RSA_FULL, #CRYPT_VERIFYCONTEXT) = 0
    CryptAcquireContext_(@hProv, #Null, #MS_STRONG_PROV, #PROV_RSA_FULL, #CRYPT_NEWKEYSET|#CRYPT_VERIFYCONTEXT)
  EndIf
  ;make RSA keypair
  CryptGenKey_(hProv,#CALG_RSA_KEYX,#CRYPT_EXPORTABLE,@hKey)
  ;set public key
  CryptExportKey_(hKey,0,#PUBLICKEYBLOB,0,0,@keylength)
  *publickey=AllocateMemory(keylength)
  CryptExportKey_(hKey,0,#PUBLICKEYBLOB,0,*publickey,@keylength)
  ;set private key
  CryptExportKey_(hKey,0,#PRIVATEKEYBLOB,0,0,@keylength)
  *privatekey=AllocateMemory(keylength)
  CryptExportKey_(hKey,0,#PRIVATEKEYBLOB,0,*privatekey,@keylength)
  CryptDestroyKey_(hKey)
  CryptReleaseContext_(hProv,0)
  ;according to MSDN this is what actually deletes key pair from CSP
  If CryptAcquireContext_(@hProv,#Null,#MS_STRONG_PROV,#PROV_RSA_FULL,#CRYPT_DELETEKEYSET)
    CryptReleaseContext_(hProv,0)
  EndIf
  rsa\keysize=keylength
  CopyMemory(*privatekey,*private,MemorySize(*privatekey))
  CopyMemory(*publicKey,*public,MemorySize(*publicKey))
  FreeMemory(*privatekey)
  FreeMemory(*publickey)
EndProcedure


string.s="Hallo12345678"
*cipherBlock=AllocateMemory(StringByteLength(string)-1)
PokeS(*cipherBlock,string,Len(string),#PB_String_NoZero)
makekeys(rsa\priv,rsa\pub)
encrypt(*cipherBlock,MemorySize(*cipherBlock),rsa\pub)
Debug PeekS(*cipherBlock,MemorySize(*cipherBlock),#PB_Unicode)
Debug PeekS(*cipherBlock,MemorySize(*cipherBlock),#PB_Ascii)
Debug PeekS(*cipherBlock,MemorySize(*cipherBlock),#PB_UTF8)
decrypt(*cipherBlock,MemorySize(*cipherBlock),rsa\priv)
Debug PeekS(*cipherBlock,MemorySize(*cipherBlock),#PB_Unicode)
Debug PeekS(*cipherBlock,MemorySize(*cipherBlock),#PB_Ascii)
Debug PeekS(*cipherBlock,MemorySize(*cipherBlock),#PB_UTF8)
End

Re: RSA crypto with Windows CSP

Posted: Sat May 20, 2017 4:59 pm
by Kwai chang caine
Hello surely again a history of UNICODE :|
W10 X64 v5.60(x86)

Code: Select all

㢶턳ꙭ㥼欔�锔䎾懣鳷⮊௥ӹ챹瓶ᩁཞ颵歈뼻㠌꾐娡揾
㢶턳ꙭ㥼欔�锔䎾懣鳷⮊௥ӹ챹瓶ᩁཞ颵歈뼻㠌꾐娡揾
and IMA at this line

Code: Select all

FreeMemory(*cipherBlock)

Re: RSA crypto with Windows CSP

Posted: Sat May 20, 2017 7:16 pm
by tj1010
Kwai chang caine wrote:Hello surely again a history of UNICODE :|
W10 X64 v5.60(x86)

Code: Select all

㢶턳ꙭ㥼欔�锔䎾懣鳷⮊௥ӹ챹瓶ᩁཞ颵歈뼻㠌꾐娡揾
㢶턳ꙭ㥼欔�锔䎾懣鳷⮊௥ӹ챹瓶ᩁཞ颵歈뼻㠌꾐娡揾
and IMA at this line

Code: Select all

FreeMemory(*cipherBlock)
The functions are all unicode safe without a unicode variant. No flag on PeekS works. I'm guessing it's a parameter to one of the CSP functions or the "blob" format..

I haven't had a chance to look at the blob structure in a run-time debugger yet. MSDN seems to completely lack documentation of some aspects of CSP and you have to reverse engineer some of these out-buffers. All the code on these forums either generated keys wrong or kept them in the container between encryption and decryption..