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 – |