Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

go

des

crypt

I am currently playing around with an example from the book Violent Python. You can see my implementation here

I am now trying to implement the same script in Go to compare performance, note I am completely new to Go. Opening the file and iterating over the lines is fine, however I cannot figure out how to use the "crypto" library to hash the string in the same way as Python's crypt.crypt(str_to_hash, salt). I thought it maybe something like

import "crypto/des"
des.NewCipher([]byte("abcdefgh"))

However, no cigar. Any help would be much appreciated as it'd be really interesting to compare Go's parallel performance to Python's multithreaded.

Edit: Python docs for crypt.crypt

like image 942
igniteflow Avatar asked Jan 01 '13 11:01

igniteflow


People also ask

What does crypt () do in Python?

crypt. crypt(password) will return the hash of password. You store the hash instead of the clear text password. That way, you can't lose the password to a hacker because you don't have it.

How do I use crypt on Windows?

Right-click (or press and hold) a file or folder and select Properties. Select the Advanced button and select the Encrypt contents to secure data check box. Select OK to close the Advanced Attributes window, select Apply, and then select OK.


3 Answers

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)

like image 139
Nick Craig-Wood Avatar answered Oct 25 '22 09:10

Nick Craig-Wood


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.

like image 34
snap Avatar answered Oct 25 '22 09:10

snap


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!?!"
like image 39
zzzz Avatar answered Oct 25 '22 09:10

zzzz