Esempio n. 1
0
// hash password and salt
func (ctx *Context) hash(password []byte, salt []byte) ([]byte, error) {

	if len(password) == 0 {
		return nil, ErrPassword
	}
	if len(salt) == 0 {
		return nil, ErrSalt
	}

	hash := make([]byte, ctx.HashLen)

	// optional secret
	secret := (*C.uint8_t)(nil)
	if len(ctx.Secret) > 0 {
		secret = (*C.uint8_t)(&ctx.Secret[0])
	}

	// optional associated data
	associatedData := (*C.uint8_t)(nil)
	if len(ctx.AssociatedData) > 0 {
		associatedData = (*C.uint8_t)(&ctx.AssociatedData[0])
	}

	// optional flags
	flags := C.ARGON2_DEFAULT_FLAGS
	if ctx.Flags != 0 {
		flags = ctx.Flags
	}

	// wrapper to overcome go pointer passing limitations
	result := C.argon2_wrapper(
		(*C.uint8_t)(&hash[0]), C.uint32_t(ctx.HashLen),
		(*C.uint8_t)(&password[0]), C.uint32_t(len(password)),
		(*C.uint8_t)(&salt[0]), C.uint32_t(len(salt)),
		secret, C.uint32_t(len(ctx.Secret)),
		associatedData, C.uint32_t(len(ctx.AssociatedData)),
		C.uint32_t(ctx.Iterations),
		C.uint32_t(ctx.Memory),
		C.uint32_t(ctx.Parallelism),
		C.uint32_t(ctx.Parallelism),
		C.uint32_t(ctx.Version),
		nil, nil,
		C.uint32_t(flags),
		C.argon2_type(ctx.Mode))

	if result != C.ARGON2_OK {
		return nil, Error(result)
	}

	return hash, nil
}
Esempio n. 2
0
// HashEncoded hashes a password and produces a crypt-like encoded string.
func HashEncoded(ctx *Context, password []byte, salt []byte) (string, error) {
	if ctx == nil {
		return "", ErrContext
	}

	if len(password) == 0 {
		return "", ErrPassword
	}
	if len(salt) == 0 {
		return "", ErrSalt
	}

	encodedlen := C.argon2_encodedlen(
		C.uint32_t(ctx.Iterations),
		C.uint32_t(ctx.Memory),
		C.uint32_t(ctx.Parallelism),
		C.uint32_t(len(salt)),
		C.uint32_t(ctx.HashLen))

	s := make([]byte, encodedlen)

	result := C.argon2_hash(
		C.uint32_t(ctx.Iterations),
		C.uint32_t(ctx.Memory),
		C.uint32_t(ctx.Parallelism),
		unsafe.Pointer(&password[0]), C.size_t(len(password)),
		unsafe.Pointer(&salt[0]), C.size_t(len(salt)),
		nil, C.size_t(ctx.HashLen),
		(*C.char)(unsafe.Pointer(&s[0])), C.size_t(encodedlen),
		C.argon2_type(ctx.Mode),
		C.uint32_t(ctx.Version))

	if result != C.ARGON2_OK {
		return "", Error(result)
	}

	// Strip trailing null byte(s)
	s = bytes.TrimRight(s, "\x00")
	return string(s), nil
}
Esempio n. 3
0
// VerifyEncoded verifies an encoded Argon2 hash s against a plaintext password.
func VerifyEncoded(s string, password []byte) (bool, error) {
	mode, err := getMode(s)
	if err != nil {
		return false, err
	}

	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))

	result := C.argon2_verify(
		cs,
		unsafe.Pointer(&password[0]),
		C.size_t(len(password)),
		C.argon2_type(mode))

	if result == C.ARGON2_OK {
		return true, nil
	} else if result == C.ARGON2_VERIFY_MISMATCH {
		return false, nil
	}

	// argon2_verify always seems to return an error in this case...
	return false, Error(result)
}