RSA crypto with Windows CSP

Windows specific forum
User avatar
tj1010
Enthusiast
Enthusiast
Posts: 623
Joined: Mon Feb 25, 2013 5:51 pm
Location: US or Estonia
Contact:

RSA crypto with Windows CSP

Post 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
Last edited by tj1010 on Sat May 20, 2017 7:13 pm, edited 1 time in total.
The truth hurts.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: RSA crypto with Windows CSP

Post 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)
ImageThe happiness is a road...
Not a destination
User avatar
tj1010
Enthusiast
Enthusiast
Posts: 623
Joined: Mon Feb 25, 2013 5:51 pm
Location: US or Estonia
Contact:

Re: RSA crypto with Windows CSP

Post 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..
The truth hurts.
Post Reply