OpenSSL crypto using SSH keys

Share your advanced PureBasic knowledge/code with the community.
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

OpenSSL crypto using SSH keys

Post by vwidmer »

Please feel free to improve on and post your improvements. Thanks

Code: Select all

;EnableExplicit

Enumeration
  #RSA_PKCS1_PADDING      = 1
  #RSA_SSLV23_PADDING     = 2
  #RSA_NO_PADDING         = 3
  #RSA_PKCS1_OAEP_PADDING = 4
  #RSA_X931_PADDING       = 5
  #RSA_PKCS1_PADDING_SIZE = 11
EndEnumeration

ImportC ""
  strlen.l(*cs) ;get Ascii lengh
EndImport

PrototypeC.l SSLeay_version(witch.l)
PrototypeC.l BIO_s_mem()
PrototypeC.l BIO_new(*type)
PrototypeC.l BIO_write(*bio, *buf, len.l)
PrototypeC.l BIO_free(*bio) 
PrototypeC.l PEM_read_bio_RSA_PUBKEY(*bp, *rsa, *cb, *u) 
PrototypeC.l PEM_read_bio_RSAPrivateKey(*bp, *rsa, *cb, *u) 
PrototypeC.l RSA_public_encrypt(flen.l, *from, *to, *rsa, padding.l) 
PrototypeC.l RSA_public_decrypt(flen.l, *from, *to, *rsa, padding.l) 
PrototypeC.l RSA_private_ecrypt(flen.l, *from, *to, *rsa, padding.l) 
PrototypeC.l RSA_private_decrypt(flen.l, *from, *to, *rsa, padding.l) 
PrototypeC.l RSA_free(*rsa) 

Procedure.s BashRun(prun.s)
  Program = RunProgram("bash", "-c "+#DQUOTE$+prun.s+#DQUOTE$+"","", #PB_Program_Open|#PB_Program_Read|#PB_Program_Write|#PB_Program_Error|#PB_Program_UTF8)
  If Program
    While ProgramRunning(Program)
      If AvailableProgramOutput(Program)
        Output$ + ReadProgramString(Program) + #LF$
      EndIf
    Wend
    CloseProgram(Program) ; Close the connection to the program
  EndIf
  ProcedureReturn Output$
EndProcedure

Define Library$=""
CompilerIf #PB_Compiler_OS = #PB_OS_Linux Or  #PB_Compiler_OS = #PB_OS_Windows
  Debug "Valid OS"
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    Library$ ="/usr/lib/libcrypto.so.1.0.0"
  CompilerElse
    Library$ ="libeay32.dll"
  CompilerEndIf
CompilerElse
  CompilerError "Error Invalid OS"
  End
CompilerEndIf


;Initialize
If OpenLibrary(0, Library$)
  Global SSLeay_version.SSLeay_version = GetFunction(0, "SSLeay_version")
  Global BIO_s_mem.BIO_s_mem = GetFunction(0, "BIO_s_mem")
  Global BIO_new.BIO_new = GetFunction(0, "BIO_new")
  Global BIO_write.BIO_write = GetFunction(0, "BIO_write")
  Global BIO_free.BIO_free = GetFunction(0, "BIO_free")
  Global PEM_read_bio_RSA_PUBKEY.PEM_read_bio_RSA_PUBKEY = GetFunction(0, "PEM_read_bio_RSA_PUBKEY")
  Global PEM_read_bio_RSAPrivateKey.PEM_read_bio_RSAPrivateKey = GetFunction(0, "PEM_read_bio_RSAPrivateKey")
  Global RSA_public_encrypt.RSA_public_encrypt = GetFunction(0, "RSA_public_encrypt")
  Global RSA_public_decrypt.RSA_public_decrypt = GetFunction(0, "RSA_public_decrypt")
  Global RSA_private_ecrypt.RSA_private_ecrypt = GetFunction(0, "RSA_private_ecrypt")
  Global RSA_private_decrypt.RSA_private_decrypt = GetFunction(0, "RSA_private_decrypt")
  Global RSA_free.RSA_free = GetFunction(0, "RSA_free")
  Debug "SSLeay_version: " + PeekS(SSLeay_version(0),-1,#PB_Ascii )
EndIf

; Debug PublicKey$
PublicKey$ = ""
  If ReadFile(0, "id_rsa.pub")   ; if the file could be read, we continue...
    While Eof(0) = 0                             ; loop as long the 'end of file' isn't reached
      rd$ = ReadString(0) + Chr(13) + Chr(10)      
      If Left(rd$,7) = "ssh-rsa"
        PublicKey$ = BashRun("ssh-keygen -e -f id_rsa.pub -m PKCS8") + #LF$
        Break
      Else        
        PublicKey$ + rd$
      EndIf     
    Wend
    CloseFile(0)               ; close the previously opened file
  Else
    MessageRequester("Information","Couldn't open the file!")
  EndIf
  ;Debug PublicKey$
  
  PrivateKey$ = ""
  If ReadFile(0, "id_rsa")   ; if the file could be read, we continue...
    While Eof(0) = 0           ; loop as long the 'end of file' isn't reached
      PrivateKey$ + ReadString(0) + Chr(13) + Chr(10)     ; display line by line in the debug window
    Wend
    CloseFile(0)               ; close the previously opened file
  Else
    MessageRequester("Information","Couldn't open the file!")
  EndIf
  ;Debug PrivateKey$
  
;Convert to Ascii Keys
Global *PublicKey=Ascii(PublicKey$)
Global *PrivateKey=Ascii(PrivateKey$)


Procedure.s _RSA_Public_Encrypt(Message.s, *Key, *Message0)
  Define  EncryptedString.s = ""
  Define *BIO = BIO_new(BIO_s_mem())
  Debug "*BIO: " + *BIO
  If *BIO
    Define Len = strlen(*Key)
    Debug "LenKey: " + Len

    If BIO_write(*BIO, *Key, Len)
      Define *RSA = PEM_read_bio_RSA_PUBKEY(*BIO, #Null, #Null, #Null)
      Debug "*RSA: " + *RSA
      If *RSA
        Len = StringByteLength(Message)
        Define *Buffer = AllocateMemory(256)
        Len = RSA_public_encrypt(Len, @Message, *Buffer, *RSA, #RSA_PKCS1_PADDING)
         Debug "RSA_public_encrypt Len: " + Len
        If Len>0
          CopyMemory(*Buffer, *Message0, 256)
          EncryptedString = PeekS(*Buffer, Len)
        EndIf
        FreeMemory(*Buffer)
      EndIf
      RSA_free(*RSA)
    EndIf
    BIO_Free(*BIO)
  EndIf
  ProcedureReturn EncryptedString
EndProcedure

Procedure.s _RSA_Private_Decrypt(*Message, *Key)
  Define DecryptedString.s = ""
  Define *BIO = BIO_new(BIO_s_mem())
  Debug "*BIO: "  + *BIO 
  If *BIO
    Define Len = strlen(*Key)
     Debug "Len: "  + Len 
    If BIO_write(*BIO, *Key, Len)
      Define  *RSA = PEM_read_bio_RSAPrivateKey(*BIO, #Null, #Null, #Null)
        Debug "*RSA: "  + *RSA 
      If *RSA
        Len = MemorySize(*Message)
        Define *Buffer = AllocateMemory(256)
        Len = RSA_private_decrypt(Len, *Message, *Buffer, *RSA, #RSA_PKCS1_PADDING)
        If Len>0
          DecryptedString = PeekS(*Buffer, Len)
        EndIf
        FreeMemory(*Buffer)
      EndIf
      RSA_free(*RSA)
    EndIf
    BIO_Free(*BIO)
  EndIf
  ProcedureReturn DecryptedString
EndProcedure

Define StringToEncrypted$="Hello Purebasic"
Debug "String to Encrypt: " + StringToEncrypted$
Define *Mes = AllocateMemory(256)
Define Encrypted$=_RSA_Public_Encrypt(StringToEncrypted$,*PublicKey,*Mes)
Debug "String Encrypted Base64: " + Base64Encoder(@Encrypted$,StringByteLength(Encrypted$))

Define Decrypted$=_RSA_Private_Decrypt(*Mes, *PrivateKey)
Debug "String Decrypted: " + Decrypted$
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA