Golang : Derive cryptographic key from passwords with Argon2



Tags : golang aes cryptographic argon key-password

Argon2 is a method used to derive cryptographic key from passwords which has a few advantages over the "traditional method" of key generation from passwords. To learn more about the Argon2 method and the advantage it offers, please see https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf

Below is an example adapted from previous AES tutorial, but this time ... instead of hard coding the AES key, we will use Argon2 to generate the key from our password.

Here you go!


 package main

 import (
  "crypto/aes"
  "crypto/cipher"
  "crypto/rand"
  "fmt"

  "golang.org/x/crypto/argon2"
 )

 func main() {

  passwd := []byte("password")
  salt := randStr(32, "alphanum") // generate a 32 bytes of random alpha-numeric string

  // read more the advantage of using Argon2 to derive cryptographic keys from password
  //https://tip.golang.org/pkg/golang.org/x/crypto/argon2/
  argon2key := argon2.IDKey(passwd, salt, 1, 64*1024, 4, 32)

  fmt.Println("Salt : ", salt)
  fmt.Println("Argon2 Key : ", argon2key)

  fmt.Println("Size of argon2 key : ", len(argon2key))

  // taken from  https://socketloop.com/tutorials/golang-how-to-encrypt-with-aes-crypto
  // instead of hardcoding our 32 bytes AES key, we now use the key from Argon2

  block, err := aes.NewCipher([]byte(argon2key))

  if err != nil {
 panic(err)
  }

  fmt.Printf("%d bytes NewCipher key with block size of %d bytes\n", len(argon2key), block.BlockSize)

  // 16 bytes for AES-128, 24 bytes for AES-192, 32 bytes for AES-256
  ciphertext := []byte("abcdef1234567890ghijklmno98765432")
  iv := ciphertext[:aes.BlockSize] // const BlockSize = 16, doesn't matter if AES-256 or AES-192... still use this constant

  // verify
  // fmt.Println(string(iv))

  secret := []byte("Hello! 妳好嗎?")

  // encrypt
  encrypter := cipher.NewCFBEncrypter(block, iv)

  encrypted := make([]byte, len(secret))
  encrypter.XORKeyStream(encrypted, secret)
  fmt.Printf("%s encrypted to %v\n", secret, encrypted)

  // verify
  //fmt.Printf("%s encrypted to %s\n", secret, string(encrypted))

  // let's decrypt back and see how it goes

  decrypter := cipher.NewCFBDecrypter(block, iv) // simple!

  decrypted := make([]byte, len(encrypted))
  decrypter.XORKeyStream(decrypted, encrypted)

  fmt.Printf("%s decrypted to %s\n", string(encrypted), decrypted)

 }

 // MODIFIED from https://socketloop.com/tutorials/golang-how-to-generate-random-string
 func randStr(strSize int, randType string) []byte {

  var dictionary string

  if randType == "alphanum" {
 dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  }

  if randType == "alpha" {
 dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  }

  if randType == "number" {
 dictionary = "0123456789"
  }

  var bytes = make([]byte, strSize)
  rand.Read(bytes)
  for k, v := range bytes {
 bytes[k] = dictionary[v%byte(len(dictionary))]
  }
  return bytes
 }

Sample output:

Salt : [79 86 116 122 119 119 86 103 76 114 100 85 78 52 68 114 99 54 101 118 99 121 68 81 119 77 115 52 115 102 112 114]

Argon2 Key : [151 57 205 221 57 249 116 92 116 49 39 27 249 199 53 72 203 75 105 96 108 251 91 180 217 231 14 42 160 210 222 169]

Size of argon2 key : 32

32 bytes NewCipher key with block size of 4930928 bytes

Hello! 妳好嗎? encrypted to [19 124 253 101 212 157 235 168 47 158 7 27 145 220 53 5 74]

|�eԝ�/��5J decrypted to Hello! 妳好嗎?

Happy coding!

References:

https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf

https://socketloop.com/tutorials/golang-how-to-encrypt-with-aes-crypto

https://socketloop.com/tutorials/golang-how-to-generate-random-string

https://tip.golang.org/pkg/golang.org/x/crypto/argon2/

https://socketloop.com/tutorials/golang-automatically-figure-out-array-length-size-with-three-dots

  See also : Golang : Encrypt and decrypt data with AES crypto



Tags : golang aes cryptographic argon key-password

By Adam Ng(黃武俊)

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement