by Anish
Posted on Monday December 17 , 2018
This sample chapter extracted from the book, Go Lang Cryptography for Developers . The Book theme isCryptography is for EveryOne. Learn from Crypto Principle to Applied Cryptography With Practical Example Grab a Copy
NaCl (pronounced "salt") is a new easy-to-use high-speed software library for network communication, encryption, decryption, signatures, etc. NaCl's goal is to provide all of the core operations needed to build higher-level cryptographic tools.
The Nacl Box uses the given public and private (secret) keys to derive a shared key, which is used with the nonce given to encrypt the given messages and to decrypt the given ciphertexts.
The same shared key will be generated from both pairing of keys, so given two keypairs belonging to Alice (pkalice, skalice) and Bob (pkbob, skbob), the key derived from (pkalice, skbob) will equal that from (pkbob, skalice).
golang.org/x/crypto/nacl/box authenticates and encrypts small messages using public-key cryptography.
Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate messages. The length of messages is not hidden.
func Seal
appends an encrypted and authenticated copy of message to out, which will be Overhead bytes longer than the original and must not overlap it. The nonce must be unique for each distinct message for a given pair of keys.
func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte
func Open
Open authenticates and decrypts a box produced by Seal and appends the message to out, which must not overlap box. The output will be Overhead bytes smaller than box
func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool)
func GenerateKey
GenerateKey generates a new public/private key pair suitable for use with Seal and Open
func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error)
The following example will show how to use NACL box, to secretly send encrypted and authenticated copy of message from Alice to Bob
package main
import (
crypto_rand "crypto/rand"
"fmt"
"golang.org/x/crypto/nacl/box"
"io"
)
func main() {
plaintext := "Hello 8gwifi.org using go lang Box Example"
pkalice, skalice, err := box.GenerateKey(crypto_rand.Reader)
if err != nil {
panic(err)
}
pkbob, skbob, err := box.GenerateKey(crypto_rand.Reader)
if err != nil {
panic(err)
}
fmt.Printf("Original Text: %s\n", plaintext)
fmt.Println("====NACL Box Seal/ Open====")
// You must use a different nonce for each message you encrypt with the
// same key. Since the nonce here is 192 bits long, a random value
// provides a sufficiently small probability of repeats. var nonce [24]byte
if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
panic(err)
}
// This encrypts msg and appends the result to the nonce.
encrypted := box.Seal(nonce[:], []byte(plaintext), &nonce, pkbob, skalice)
fmt.Printf("Alice Send Encrypted Message to Bob %x\n", encrypted)
// The recipient can decrypt the message using their private key and the
// sender's public key. When you decrypt, you must use the same nonce you
// used to encrypt the message. One way to achieve this is to store the
// nonce alongside the encrypted message. Above, we stored the nonce in the
// first 24 bytes of the encrypted text.
var decryptNonce [24]byte
copy(decryptNonce[:], encrypted[:24])
decrypted, ok := box.Open(nil, encrypted[24:], &decryptNonce, pkalice, skbob)
if !ok {
panic("decryption error")
}
fmt.Println("Bob Read Message[", string(decrypted), "]")
}
The output
$ go run naclbox.go
Original Text: Hello 8gwifi.org using go lang Box Example
====NACL Box Seal/ Open====
Alice Send Encrypted Message to Bob 420d83bc6d773bd0597002edc430ae44452d60ba7fa3402b3cdd827343b10a9c0c0a783a1aeb81829a52c3ed15b58568620fc4c807abbfbb48cafe9370567b6201bc33f5289a8d2cf227cd57d512177e22fa
Bob Read Message[ Hello 8gwifi.org using go lang Box Example ]
Nacl Box Faster Computing with Shared Key
The shared key can be used to speed up processing when using the same, pair of keys repeatedly. To achieve this use the go lang functions
func SealAfterPrecomputation
performs the same actions as Seal, but takes a shared key as generated by Precompute.
func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte
func OpenAfterPrecomputation
n performs the same actions as Open, but takes a shared key as generated by Precompute.
func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool)
NACL Box Precompute Example
package main
import (
crypto_rand "crypto/rand" // Custom so it's clear which rand we're using.
"fmt"
"golang.org/x/crypto/nacl/box"
"io"
)
func main() {
plaintext := "Hello 8gwifi.org using go lang Box Example"
pkalice, skalice, err := box.GenerateKey(crypto_rand.Reader)
if err != nil {
panic(err)
}
pkbob, skbob, err := box.GenerateKey(crypto_rand.Reader)
if err != nil {
panic(err)
}
fmt.Printf("Original Text: %s\n", plaintext)
fmt.Println("====NACL Box SealAfterPrecomputation/ OpenAfterPrecomputation====")
// You must use a different nonce for each message you encrypt with the
// same key. Since the nonce here is 192 bits long, a random value
// provides a sufficiently small probability of repeats.
var nonce [24]byte
if _, err := io.ReadFull(crypto_rand.Reader, nonce[:]); err != nil {
panic(err)
}
// The shared key can be used to speed up processing when using the same
// pair of keys repeatedly. sharedEncryptKey := new([32]byte)
box.Precompute(sharedEncryptKey, pkbob, skalice)
fmt.Printf("Shared Key [%x\n", *sharedEncryptKey, "]")
// This encrypts msg and appends the result to the nonce.
encrypted := box.SealAfterPrecomputation(nonce[:], []byte(plaintext), &nonce, sharedEncryptKey)
fmt.Printf("Alice Send Encrypted Message to Bob %x\n", &encrypted)
// The shared key can be used to speed up processing when using the same
// pair of keys repeatedly. var sharedDecryptKey [32]byte
box.Precompute(&sharedDecryptKey, pkalice, skbob)
// The recipient can decrypt the message using their private key and the
// sender's public key. When you decrypt, you must use the same nonce you
// used to encrypt the message. One way to achieve this is to store the
// nonce alongside the encrypted message. Above, we stored the nonce in the
// first 24 bytes of the encrypted text. var decryptNonce [24]byte
copy(decryptNonce[:], encrypted[:24])
decrypted, ok := box.OpenAfterPrecomputation(nil, encrypted[24:], &decryptNonce, &sharedDecryptKey)
if !ok {
panic("decryption error")
}
fmt.Println("Bob Read Message[", string(decrypted), "]")
}
The output
$ go run naclbox1.go
Original Text: Hello 8gwifi.org using go lang Box Example
====NACL Box SealAfterPrecomputation/ OpenAfterPrecomputation====
Shared Key [20e4228e59d552f15ab04a67269b792957d7a71400b353940bcd13b225795ec3
Alice Send Encrypted Message to Bob &3e6b0011dfcfcd9163f7d3cb68eeadf683f941f7dfca1b3c7637bf9e0fe75563b3db93ef7f357f475b7c4d1c9789c8e396951488b0cc1892668dcf9b3ed10d37feebd059622175071de065394c31478bdb0d
Bob Read Message[ Hello 8gwifi.org using go lang Box Example ]
Secret key encryption (also called symmetric key encryption) is analogous to a safe. You can store something secret through it and anyone who has the key can open it and view the contents. SecretBox functions as just such a safe, and like any good safe any attempts to tamper with the contents are easily detected.
Go lang Package secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with secret-key cryptography. The length of messages is not hidden.
func Seal
appends an encrypted and authenticated copy of message to out, which must not overlap message. The key and nonce pair must be unique for each distinct message and the output will be Overhead bytes longer than message
func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte
func open
authenticates and decrypts a box produced by Seal and appends the message to out, which must not overlap box. The output will be Overhead bytes smaller than box.
func Open(out, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool)
Note: secretbox encrypts and authenticates small messages.
The following example will show how to use NACL secretbox, to perform Secret key encryption.
import (
"crypto/rand"
"fmt"
"golang.org/x/crypto/nacl/secretbox"
"io"
)
func main() {
plaintext := "Hello 8gwifi.org using go lang secretbox esample"
// Do not Use this Key, This is for Demo Purpose only
key := "myverystrongpasswordo32bitlength"
var secretKey [32]byte
copy(secretKey[:], key)
fmt.Printf("Original Text: %s\n", plaintext)
fmt.Println("====NACL secretbox Seal/ Open====")
// You must use a different nonce for each message you encrypt with the
// same key. Since the nonce here is 192 bits long, a random value
// provides a sufficiently small probability of repeats.
var nonce [24]byte
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
panic(err)
}
encrypted := secretbox.Seal(nonce[:], []byte(plaintext), &nonce, &secretKey)
fmt.Printf("Encrypted Message: %x\n", encrypted)
// When you decrypt, you must use the same nonce and key you used to
// encrypt the message. One way to achieve this is to store the nonce
// alongside the encrypted message. Above, we stored the nonce in the first
// 24 bytes of the encrypted text. var decryptNonce [24]byte
copy(decryptNonce[:], encrypted[:24])
decrypted, ok := secretbox.Open(nil, encrypted[24:], &decryptNonce, &secretKey)
if !ok {
panic("decryption error")
}
fmt.Println(string(decrypted))
}
The output
$ go run naclsecretbox.go
Original Text: Hello 8gwifi.org using go lang secretbox esample
====NACL secretbox Seal/ Open====
Encrypted Message: fc62734e5c73ceec5e3dfe75a439bc85d13138e97423e79a7fbb17ceef34cc0f47fe26d330cf83fe3210d2a93815e3706be29dce5a282c764001dd6d471781efdf5568a2cc3220cba7f29a7fa041565010c04a0ed1b76b78
Hello 8gwifi.org using go lang secretbox esample
Nacl Message is done with go lang function auth
func sum
generates an authenticator for m using a secret key and returns the 32-byte digest.
func Sum(m []byte, key *[KeySize]byte) *[Size]byte
func verify
checks that digest is a valid authenticator of message m under the given secret key. Verify does not leak timing information.
func Verify(digest []byte, m []byte, key *[KeySize]byte) bool
The following example will show how to use NACL auth, to perform message authentication of a given message
package main
import (
"fmt"
"golang.org/x/crypto/nacl/auth"
)
func main() {
plaintext := "Hello 8gwifi.org using go lang auth esample"
// Do not Use this Key, This is for Demo Purpose only
key := "myverystrongpasswordo32bitlengt"
var secretKey [32]byte
copy(secretKey[:], key)
fmt.Printf("Original Text: %s\n", plaintext)
fmt.Println("====NACL Message Authentication====")
mac := auth.Sum([]byte(plaintext), &secretKey)
fmt.Printf("MAC %x\n", *mac)
result := auth.Verify(mac[:], []byte(plaintext), &secretKey)
fmt.Println("Verified : ", result)
badResult := auth.Verify(mac[:], []byte("different message"), &secretKey)
fmt.Println("Verified : ", badResult)
}
The output
$ go run naclauth.go
Original Text: Hello 8gwifi.org using go lang auth esample
====NACL Message Authentication====
MAC 2a6bb7feb6b2c175219abcc16fb7c472e48752212cebc4aada48a49d767cdbb5
Verified : true
Verified : false
Digital signatures allow you to publish a public key, and then you can use your private signing key to sign messages. Others who have your public key can then use it to validate that your messages are actually authentic.
Nacl Digital Signature is done with go lang function sign
func GenerateKey
generates a new public/private key pair suitable for use with Sign and Open.
func GenerateKey(rand io.Reader) (publicKey *[32]byte, privateKey *[64]byte, err error)
func Open
verifies a signed message produced by Sign and appends the message to out, which must not overlap the signed message.
func Open(out, signedMessage []byte, publicKey *[32]byte) ([]byte, bool)
func sign
appends a signed copy of message to out
func Sign(out, message []byte, privateKey *[64]byte) []byte
The following example will show how to use NACL digital signature.
package main
import (
"crypto/rand"
"fmt"
"golang.org/x/crypto/nacl/sign"
)
func main() {
plaintext := "Hello 8gwifi.org using go lang nacl signing esample"
fmt.Printf("Original Text: %s\n", plaintext)
fmt.Println("====NACL Digital Signature====")
publicKey, privateKey, _ := sign.GenerateKey(rand.Reader)
// Signing of Message is Perfomed with Private Key
signedMessage := sign.Sign(nil, []byte(plaintext), privateKey)
fmt.Printf("Message Signature %x\n ", signedMessage)
// Verification of the Message is performed with Public Key
_ , ok := sign.Open(nil, signedMessage, publicKey)
f !ok {
fmt.Printf("failed to verify signed message")
return
}
fmt.Printf("Verification Passed ")
}
The output
$ go run naclsign.go
Original Text: Hello 8gwifi.org using go lang nacl signing esample
====NACL Digital Signature====
Message Signature 1020e3901fc37f3c792a3d435ce7abca877c5171971227b6430f778ef8c245764149185abcef409de7e8e221afa723356363c017a1a46273c969b4809d52920e48656c6c6f203867776966692e6f7267207573696e6720676f206c616e67206e61636c207369676e696e67206573616d706c65
Verifification Passed
{pagebreak}
Thanku for reading !!! Give a Share for Support
Instead of directly asking for donations, I'm thrilled to offer you all nine of my books for just $9 on leanpub By grabbing this bundle you not only help cover my coffee, beer, and Amazon bills but also play a crucial role in advancing and refining this project. Your contribution is indispensable, and I'm genuinely grateful for your involvement in this journey!
Any private key value that you enter or we generate is not stored on this site, this tool is provided via an HTTPS URL to ensure that private keys cannot be stolen, for extra security run this software on your network, no cloud dependency