Browse Source

initial import

Bozhin Zafirov 7 years ago
parent
commit
8e3d5b88aa
2 changed files with 77 additions and 1 deletions
  1. 1 1
      LICENSE
  2. 76 0
      crypt.go

+ 1 - 1
LICENSE

@@ -1,4 +1,4 @@
-Copyright (c) <year> <owner> All rights reserved.
+Copyright (c) 2018 Bozhin Zafirov. All rights reserved.
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
 
 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

+ 76 - 0
crypt.go

@@ -0,0 +1,76 @@
+package crypt
+
+import (
+	"errors"
+	"math/rand"
+	"strings"
+	"time"
+	"unsafe"
+)
+
+// #cgo LDFLAGS: -lcrypt
+// #define _GNU_SOURCE
+// #include <crypt.h>
+// #include <stdlib.h>
+// #include <errno.h>
+import "C"
+
+// EPasswordIncorrect is a password verification failure error
+var EPasswordIncorrect = errors.New("passwords do not match")
+
+// Crypt wraps C library crypt_r
+func Crypt(Password, Salt string) (*string, error) {
+	data := C.struct_crypt_data{}
+	ckey := C.CString(Password)
+	csalt := C.CString(Salt)
+	cpass, err := C.crypt_r(ckey, csalt, &data)
+	if err != nil {
+		return nil, err
+	}
+	out := C.GoString(cpass)
+	C.free(unsafe.Pointer(ckey))
+	C.free(unsafe.Pointer(csalt))
+	return &out, nil
+}
+
+// MakeSaltSHA512 generates a random salt for SHA512
+// encrypted password hash.
+func MakeSaltSHA512() string {
+	var LetterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./")
+	salt := make([]rune, 8)
+
+	for i := range salt {
+		salt[i] = LetterRunes[rand.Intn(len(LetterRunes))]
+	}
+
+	return "$6$" + string(salt) + "$"
+}
+
+// Verify checks key against previously crypted hash
+func CompareHashAndPassword(Hash, Password string) error {
+	// ignore empty hashes
+	if len(Hash) == 0 {
+		return EPasswordIncorrect
+	}
+	// Split salt from password
+	HashItems := strings.SplitN(Hash, "$", 4)
+	Salt := "$" + HashItems[1] + "$" + HashItems[2] + "$"
+
+	hash, err := Crypt(Password, Salt)
+	if err != nil {
+		// Crypt error
+		return err
+	}
+
+	if *hash == Hash {
+		// Passwords match
+		return nil
+	}
+
+	return EPasswordIncorrect
+}
+
+func init() {
+	// Initialize RNG seed
+	rand.Seed(time.Now().UnixNano())
+}