What is Go's equivalent to Python's crypt.crypt?

一世执手 提交于 2019-12-05 10:34:13

crypt is very easy to wrap with cgo, eg

package main

import (
    "fmt"
    "unsafe"
)

// #cgo LDFLAGS: -lcrypt
// #define _GNU_SOURCE
// #include <crypt.h>
// #include <stdlib.h>
import "C"

// crypt wraps C library crypt_r
func crypt(key, salt string) string {
    data := C.struct_crypt_data{}
    ckey := C.CString(key)
    csalt := C.CString(salt)
    out := C.GoString(C.crypt_r(ckey, csalt, &data))
    C.free(unsafe.Pointer(ckey))
    C.free(unsafe.Pointer(csalt))
    return out
}

func main() {
    fmt.Println(crypt("abcdefg", "aa"))
}

Which produces this when run

aaTcvO819w3js

Which is identical to python crypt.crypt

>>> from crypt import crypt
>>> crypt("abcdefg","aa")
'aaTcvO819w3js'
>>> 

(Updated to free the CStrings - thanks @james-henstridge)

I believe there isn't currently any publicly available package for Go which implements the old-fashioned Unix "salted" DES based crypt() functionality. This is different from the normal symmetrical DES encryption/decryption which is implemented in the "crypto/des" package (as you have discovered).

You would have to implement it on your own. There are plenty of existing implementations in different languages (mostly C), for example in FreeBSD sources or in glibc. If you implement it in Go, please publish it. :)

For new projects it is much better to use some stronger password hashing algorithm, such as bcrypt. A good implementation is available in the go.crypto repository. The documentation is available here. Unfortunately this does not help if you need to work with pre-existing legacy password hashes.

Edited to add: I had a look at Python's crypt.crypt() implementation and found out that it is just a wrapper around the libc implementation. It would be simple to implement the same wrapper for Go. However your idea of comparing a Python implementation to a Go implementation is already ruined: you would have to implement both of them yourself to make any meaningful comparisons.

E.g.

package main

import (
        "crypto/des"
        "fmt"
        "log"
)

func main() {
        b, err := des.NewCipher([]byte("abcdefgh"))
        if err != nil {
                log.Fatal(err)
        }

        msg := []byte("Hello!?!")
        fmt.Printf("% 02x: %q\n", msg, msg)
        b.Encrypt(msg, msg)
        fmt.Printf("% 02x: %q\n", msg, msg)
        b.Decrypt(msg, msg)
        fmt.Printf("% 02x: %q\n", msg, msg)
}

(Also: http://play.golang.org/p/czYDRjtWNR)


Output:

48 65 6c 6c 6f 21 3f 21: "Hello!?!"
3e 41 67 99 2d 9a 72 b9: ">Ag\x99-\x9ar\xb9"
48 65 6c 6c 6f 21 3f 21: "Hello!?!"

Good news! There's actually an open source implementation of what you're looking for. Osutil has a crypt package that reimplements crypt in pure Go.

https://github.com/kless/osutil/tree/master/user/crypt

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!