package sys
|
|
/*
|
#cgo LDFLAGS: -lcrypto
|
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <openssl/evp.h>
|
#include <openssl/opensslv.h>
|
|
char* pw_hash(const char *password, unsigned char *salt) {
|
const EVP_MD *digest;
|
unsigned char *password_hash;
|
unsigned int hash_len;
|
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
EVP_MD_CTX context;
|
#else
|
EVP_MD_CTX *context;
|
#endif
|
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L || OPENSSL_API_COMPAT < 0x10100000L
|
OpenSSL_add_all_digests();
|
#else
|
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
|
| OPENSSL_INIT_ADD_ALL_DIGESTS \
|
| OPENSSL_INIT_LOAD_CONFIG, NULL);
|
#endif
|
|
digest = EVP_get_digestbyname("sha512");
|
if(!digest){
|
return NULL;
|
}
|
|
password_hash = malloc(64 * sizeof(unsigned char));
|
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
EVP_MD_CTX_init(&context);
|
EVP_DigestInit_ex(&context, digest, NULL);
|
EVP_DigestUpdate(&context, password, strlen(password));
|
EVP_DigestUpdate(&context, salt, 12);
|
EVP_DigestFinal_ex(&context, password_hash, &hash_len);
|
EVP_MD_CTX_cleanup(&context);
|
#else
|
context = EVP_MD_CTX_new();
|
EVP_DigestInit_ex(context, digest, NULL);
|
EVP_DigestUpdate(context, password, strlen(password));
|
EVP_DigestUpdate(context, salt, 12);
|
EVP_DigestFinal_ex(context, password_hash, &hash_len);
|
EVP_MD_CTX_free(context);
|
#endif
|
|
return password_hash;
|
}
|
*/
|
import "C"
|
import (
|
"encoding/base64"
|
"fmt"
|
"math/rand"
|
"time"
|
"unsafe"
|
)
|
|
const EVP_MAX_MD_SIZE = 64
|
const SALT_LEN = 12
|
|
func RandBytes(n int) []byte {
|
rand.Seed(time.Now().UnixNano())
|
str := "0123456789abcdefghijklmnopqrstuvwxyz"
|
bytes := []byte(str)
|
|
var result []byte
|
for i := 0; i < n; i++ {
|
result = append(result, bytes[rand.Intn(len(bytes))])
|
}
|
|
return result
|
}
|
|
/*
|
mosquitto生成用户密码的go实现
|
*/
|
func OutputNewPassword(username, password string) (text string) {
|
saltByte := RandBytes(SALT_LEN)
|
salt64 := base64.StdEncoding.EncodeToString(saltByte)
|
|
passwordPtr := C.CString(password)
|
defer C.free(unsafe.Pointer(passwordPtr))
|
|
passwordHash := C.pw_hash((*C.char)(unsafe.Pointer(passwordPtr)), (*C.uchar)(unsafe.Pointer(&saltByte[0])))
|
defer C.free(unsafe.Pointer(passwordHash))
|
|
hashByte := C.GoBytes(unsafe.Pointer(passwordHash), 64)
|
|
hash64 := base64.StdEncoding.EncodeToString(hashByte)
|
|
text = fmt.Sprintf("%s:$6$%s$%s", username, salt64, hash64)
|
|
return
|
}
|