CGO example to calculate MD5 of string

By | February 18, 2024

It was continuation of “Calculate MD5 programmatically (c++ and golang)” post. That post contains example of MD5 calculation written in Go. The Go example small and tidy, the new example contains significantly more line of code and looks cumbersome, however in demonstrate how to use openssl API from Go and includes multiple samples of CGO types conversation to or from Go types. It is the example:


package main
// #cgo CFLAGS: -fPIC
// #cgo LDFLAGS: -lssl -lcrypto
// #include <string.h>
// #include <stdlib.h>
// #include <openssl/evp.h>
import "C"
import "runtime"
import "fmt"
import "os"
import "unsafe"
func main() {
  type StringHeader struct {
    Data unsafe.Pointer
    Len int
  }
  argLen := len(os.Args)
  if argLen == 1 {
    fmt.Println("Specify string as an argument to calculate its MD5")
    os.Exit(-1)
  }
  if(runtime.GOOS == "linux") {
    pEvpCtx := C.EVP_MD_CTX_new()
    C.EVP_MD_CTX_reset(pEvpCtx)
    var pmdValue *C.uchar
    pmdValue = (*C.uchar)(C.malloc(64))
    var uiMdLength C.uint
    sLen := len(os.Args[1])
    C.memset(unsafe.Pointer(pmdValue), 0, 64)
    var ptrStr = (*StringHeader)(unsafe.Pointer(&os.Args[1]))
    var dataStr = ptrStr.Data
    C.EVP_DigestInit_ex(pEvpCtx, C.EVP_md5(), nil );
    C.EVP_DigestUpdate( pEvpCtx, dataStr, C.ulong(sLen) );
    C.EVP_DigestFinal_ex ( pEvpCtx, pmdValue, &uiMdLength );
    C.EVP_MD_CTX_free(pEvpCtx)
    var char byte
    for i := 0; i < int(uiMdLength); i++ {
      ptr := uintptr(unsafe.Pointer(pmdValue)) + uintptr(i)
      char = *(*byte)(unsafe.Pointer(ptr))
      fmt.Print(fmt.Sprintf("%02x", char))
    }
    fmt.Printf("\n");
    C.free(unsafe.Pointer(pmdValue))
  }
}

Building:


go build md5openssl.go

Testing:


./md5openssl "openssl and go"
d737c1968fcb3eb4de7bf0f3e0acf46a

echo -n "openssl and go" | md5sum
d737c1968fcb3eb4de7bf0f3e0acf46a –

Leave a Reply

Your email address will not be published. Required fields are marked *