Intro
This time, I will try implementing HMAC-SHA512.
I will use the SHA-512 function what I wrote last time.
Secret Key
HMAC needs a key and a message to get a hash value.
The key has several features.
- It is shared only by the sender and the receiver
- It can be of any length
- If its length is shorter than the byte-length of the hash function, it is first filled with zeros to make it that length
- If its length is longer than the byte-length of the hash function, it will be hashed first
It seems that "PasswordHasher" also uses the password(message) as a key.
- aspnetcore/PasswordHasher.cs - dotnet/aspnetcore - GitHub
- aspnetcore/ManagedPbkdf2Provider.cs - dotnet/aspnetcore - GitHub
Update SHA-512
Last time, I returned the result as a string value.
But I want to get the value as byte array to append the key, so I change the SHA-512 function.
sha512Hasher.go
...
func Hash(inputValues []byte) []byte {
formattedMessage := formatInput(inputValues)
computed := compute(formattedMessage)
return computed
}
...
func compute(messages []byte) []byte {
...
// get H[N]
var results []byte
for _, h := range H {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, h)
results = append(results, b...)
}
return results
}
- How can I convert an int64 into a byte array in go? - StackOverflow
- Concatenate 2 slices in golang - StackOverflow
Examples
main.go
package main
import (
"crypto/hmac"
"crypto/sha512"
"fmt"
"log"
)
func main() {
inputData := []byte("hello")
hmacSHA512Results := HashHMACSHA512(inputData, inputData)
var hresult string
for _, r := range hmacSHA512Results {
hresult += fmt.Sprintf("%02X", r)
}
log.Println(hresult)
h := hmac.New(sha512.New, inputData)
h.Write(inputData)
results := h.Sum(nil)
var result string
for _, r := range results {
result += fmt.Sprintf("%02X", r)
}
log.Println(result)
}
hmacSHA512Hasher.go
package main
const byteLength int = 128
/* compute H(K XOR opad, H(K XOR ipad, text)) */
func HashHMACSHA512(inputData, keyData []byte) []byte {
formattedKey := formatKey(keyData)
ipad := xorIPAD(formattedKey)
// append the stream of input data to the result of (K XOR ipad)
// and hash the value
innerData := Hash(append(ipad, inputData...))
opad := xorOPAD(formattedKey)
// append the H result to the result of (K XOR opad)
// and hash the value
return Hash(append(opad, innerData...))
}
func formatKey(keyData []byte) []byte {
// If its length is longer than the byte-length,
// it will be hashed first
if len(keyData) >= byteLength {
return Hash(keyData)
}
// If its length is shorter than the byte-length,
// it is first filled with zeros to make it that length
results := make([]byte, byteLength)
copy(results, keyData)
for i := len(keyData); i < byteLength; i++ {
results[i] = 0x00
}
return results
}
/* K XOR ipad(ipad = the byte 0x36 repeated B times) */
func xorIPAD(k []byte) []byte {
results := make([]byte, len(k))
for i, key := range k {
results[i] = key ^ 0x36
}
return results
}
/* K XOR opad(opad = the byte 0x5C repeated B times) */
func xorOPAD(k []byte) []byte {
results := make([]byte, len(k))
for i, key := range k {
results[i] = key ^ 0x5C
}
return results
}
Result
8F9909C45E601A31A2E6949FE6E4C739ADE74F3A0A5F9489D4E5F8BC5B71C08C998C78E14AB4C524E884A308E1E4B9902E7E76D9E1328E5A603B7DFA42604D74
8F9909C45E601A31A2E6949FE6E4C739ADE74F3A0A5F9489D4E5F8BC5B71C08C998C78E14AB4C524E884A308E1E4B9902E7E76D9E1328E5A603B7DFA42604D74
Top comments (0)