zhangzengfei
2023-09-04 e8e536d1cb52d2126c8c7ce2ba1c7a76f7208678
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
}