But since the length of all entries is fixed, it is no problem to 'build' it by hand.
Code: Select all
EnableExplicit
IncludeFile "libcurl.pbi"
Define.i curl, headerList, res, file, i
Define result$, *tsq, fileName$, SHA512$
InitNetwork()
UseSHA2Fingerprint()
fileName$ = OpenFileRequester("Choose a file for a TimeStamp", "", "All|*.*", 0)
If fileName$
  SHA512$ = FileFingerprint(fileName$, #PB_Cipher_SHA2, 512)
  If SHA512$ <> ""
    *tsq = AllocateMemory(91)
    If *tsq
      PokeA(*tsq +  0, $30)  ; Sequence
      PokeA(*tsq +  1, $59)  ; length of Sequence
      PokeA(*tsq +  2, $02)  ; Integer
      PokeA(*tsq +  3, $01)  ; length of Integer
      PokeA(*tsq +  4, $01)  ; 1 -> Version
      PokeA(*tsq +  5, $30)  ; Sequence
      PokeA(*tsq +  6, $51)  ; length of Sequence
      PokeA(*tsq +  7, $30)  ; Sequence
      PokeA(*tsq +  8, $0D)  ; length of Sequence
      PokeA(*tsq +  9, $06)  ; ObjectIDentifier
      PokeA(*tsq + 10, $09)  ; length of OID
      PokeA(*tsq + 11, $60)  ; OID: SHA512 = 2.16.840.1.101.3.4.2.3
      PokeA(*tsq + 12, $86)
      PokeA(*tsq + 13, $48)
      PokeA(*tsq + 14, $01)  ; .1
      PokeA(*tsq + 15, $65)  ; .101
      PokeA(*tsq + 16, $03)  ; .3
      PokeA(*tsq + 17, $04)  ; .4
      PokeA(*tsq + 18, $02)  ; .2
      PokeA(*tsq + 19, $03)  ; .3
      PokeA(*tsq + 20, $05)  ; Null
      PokeA(*tsq + 21, $00)  ; length of Null
      PokeA(*tsq + 22, $04)  ; Octet String
      PokeA(*tsq + 23, $40)  ; length of String: 64 bytes = 512 bits
      For i = 0 To 63
        PokeA(*tsq + 24 + i, Val("$" + Mid(SHA512$, i * 2, 2)))
      Next i
      PokeA(*tsq + 88, $01)  ; Boolean
      PokeA(*tsq + 89, $01)  ; length of Boolean
      PokeA(*tsq + 90, $FF)  ; certRequest: 00 = False, FF = True  depending on your needs
      
      file = CreateFile(#PB_Any, fileName$ + ".tsq")
      If file
        WriteData(file, *tsq, MemorySize(*tsq))
        CloseFile(file)
      EndIf
      
      curl = curl_easy_init()
      If curl
        curl_easy_setopt_str(curl, #CURLOPT_URL, "https://freetsa.org/tsr")
        
        curl_easy_setopt(curl, #CURLOPT_POST, #True)
        curl_easy_setopt(curl, #CURLOPT_POSTFIELDSIZE, MemorySize(*tsq))
        curl_easy_setopt(curl, #CURLOPT_COPYPOSTFIELDS, *tsq)
        
        curl_easy_setopt(curl, #CURLOPT_SSL_VERIFYPEER, #False)
        curl_easy_setopt(curl, #CURLOPT_SSL_VERIFYHOST, #False)
        
        headerList = curl_slist_append(headerList, "Content-Type: application/timestamp-query")
        
        curl_easy_setopt(curl, #CURLOPT_HTTPHEADER, headerList)
        
        file = CreateFile(#PB_Any, fileName$ + ".tsr")
        If file
          
          curl_easy_setopt(curl, #CURLOPT_WRITEDATA, file)
          
          curl_easy_setopt(curl, #CURLOPT_WRITEFUNCTION, @LibCurl_WriteFunction())
          
          res = curl_easy_perform(curl)
          If res = #CURLE_OK
            Debug "Ok"
          Else
            Debug "Error: " + curl_easy_strerror(res)
          EndIf
          CloseFile(file)
          
        EndIf
        
        curl_slist_free_all(headerList)
        
        curl_easy_cleanup(curl)
      EndIf
      
      FreeMemory(*tsq)
      
    EndIf
  EndIf
EndIf