// !build linux,amd64 package md5c // /* Any 32-bit or wider unsigned integer data type will do */ // typedef unsigned int MD5_u32plus; // // typedef struct { // MD5_u32plus lo, hi; // MD5_u32plus a, b, c, d; // unsigned char buffer[64]; // MD5_u32plus block[16]; // } MD5_CTX; // // void MD5_Init(MD5_CTX *ctx); // void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); // void MD5_Final(unsigned char *result, MD5_CTX *ctx); import "C" import ( "io" "unsafe" ) func context() *C.MD5_CTX { var ctx C.MD5_CTX C.MD5_Init(&ctx) return &ctx } func write(buffer []byte, ctx *C.MD5_CTX) { size := len(buffer) data := unsafe.Pointer(&buffer[0]) C.MD5_Update(ctx, data, C.ulong(size)) } func Sum(reader io.Reader) ([]byte, error) { ctx := context() var err error var length int for err == nil { byteBuffer := make([]byte, 1024*1024) length, err = reader.Read(byteBuffer) // break here since byteBuffer will go out of range // when invoking subsequent write() call if length == 0 { break } byteBuffer = byteBuffer[0:length] write(byteBuffer, ctx) } if err != io.EOF { return nil, err } outputBuffer := make([]byte, 16) coutputbuff := (*C.uchar)(unsafe.Pointer(&outputBuffer[0])) C.MD5_Final(coutputbuff, ctx) return outputBuffer, nil }