Pure Go implementation of the NaCL set of API's

Overview

go-nacl

GoDoc

This is a pure Go implementation of the API's available in NaCL: https://nacl.cr.yp.to. Compared with the implementation in golang.org/x/crypto/nacl, this library offers all of the API's present in NaCL, better compatibility with NaCL implementations written in other languages, as well as some utilities for generating and loading keys and nonces, and encrypting messages.

Many of them are simple wrappers around functions or libraries available in the Go standard library, or in the golang.org/x/crypto package. Other code I copied directly into this library with the appropriate LICENSE; if a function is longer than, say, 5 lines, I didn't write it myself. There are no dependencies outside of the standard library or golang.org/x/crypto.

The goal is to both show how to implement the NaCL functions in pure Go, and to provide interoperability between messages encrypted/hashed/authenticated in other languages, and available in Go.

Among other benefits, NaCL is designed to be misuse resistant and standardizes on the use of 32 byte keys and 24 byte nonces everywhere. Several helpers are present for generating keys/nonces and loading them from configuration, as well as for encrypting messages. You can generate a key by running openssl rand -hex 32 and use the helpers in your program like so:

import "github.com/kevinburke/nacl"
import "github.com/kevinburke/nacl/secretbox"

func main() {
    key, err := nacl.Load("6368616e676520746869732070617373776f726420746f206120736563726574")
    if err != nil {
        panic(err)
    }
    encrypted := secretbox.EasySeal([]byte("hello world"), key)
    fmt.Println(base64.StdEncoding.EncodeToString(encrypted))
}

The package names match the primitives available in NaCL, with the crypto_ prefix removed. Some function names have been changed to match the Go conventions.

Installation

go get github.com/kevinburke/nacl

Or you can Git clone the code directly to $GOPATH/src/github.com/kevinburke/nacl.

Who am I?

While you probably shouldn't trust random security code from the Internet, I'm reasonably confident that this code is secure. I did not implement any of the hard math (poly1305, XSalsa20, curve25519) myself - I call into golang.org/x/crypto for all of those functions. I also ported over every test I could find from the C/C++ code, and associated RFC's, and ensured that these libraries passed those tests.

I'm a contributor to the Go Standard Library and associated tools, and I've also been paid to do security consulting for startups, and found security problems in consumer sites.

Errata

  • The implementation of crypto_sign uses the ref10 implementation of ed25519 from SUPERCOP, not the current implementation in NaCL. The difference is that the entire 64-byte signature is prepended to the message; in the current version of NaCL, separate bits are prepended and appended to the message.

  • Compared with crypto/ed25519, this library's Sign implementation returns the message along with the signature, and Verify expects the first 64 bytes of the message to be the signature. This simplifies the API and matches the behavior of the ref10 implementation and other NaCL implementations. Sign also flips the order of the message and the private key: Sign(message, privatekey), to match the NaCL implementation.

  • Compared with golang.org/x/crypto/nacl/box, Precompute returns the shared key instead of modifying the input. In several places the code was modified to call functions that now exist in nacl.

  • Compared with golang.org/x/crypto/nacl/secretbox, Seal and Open call the onetimeauth package in this library, instead of calling golang.org/x/crypto/poly1305 directly.

Comments
  • Timing attacks

    Timing attacks

    Given that the library does not seem to protect against timing attacks it would probably be a good idea to mention that prevention of such attacks is left up to the consumer of the lib. Seems worth adding to the readme/ documentation.

    opened by insanitybit 5
  • Nonce operation advice

    Nonce operation advice

    Sorry if this generic crypto question is out of scope.

    What nonce operation mode would you suggest for a stateful message exchange protocol built on top of secretbox? I can imagine at least two options:

    • generate random nonce in every message, send length and nonce in authenticated clear text
    • hello message as above with another secret nonce in payload, derive all next nonces from that secret payload, send only authenticated length in clear text

    My use case is RPC with messages around 50-200 bytes on expensive 3g network, and shaving 24 bytes from each message is definitely worth pursuing.

    Thanks for your time.

    opened by temoto 2
  • support Ed25519 to Curve25519 keys conversion

    support Ed25519 to Curve25519 keys conversion

    This should be very useful, such as https://download.libsodium.org/doc/advanced/ed25519-curve25519.html

    golang has such plan, but seems like no progress. https://github.com/golang/go/issues/20504

    opened by leslie-wang 2
  • Verify that the message was signed with public key

    Verify that the message was signed with public key

    Hello! Thanks for the library.

    TweetNaCl has a method which verifies that the given message was signed with given PublicKey:

    nacl.sign.detached.verify = function(msg, sig, publicKey) {
    

    Is there something similar in this library?

    I saw this method but it doesn't take the message into account. I'd like to verify there's a specific nonce present in a message.

    opened by dn-l 1
  • use stdlib ed25519

    use stdlib ed25519

    opened by bsdlp 1
  • Open function issue after EasySeal or Seal

    Open function issue after EasySeal or Seal

    Hi,

    I have some doubts about how the piece of code 1 works and the 2 does not. I do not think that this was a real issue.

    • Code 1:
    package main
    
    import (
    	crypto_rand "crypto/rand"
    	"encoding/base64"
    	"fmt"
    	"github.com/kevinburke/nacl/box"
    )
    
    func main() {
    	pk, sk, err := box.GenerateKey(crypto_rand.Reader)
    	if err != nil {
    		panic(err)
    	}
    	message := "the sky is blue"
    	fmt.Printf("Plaintext message: %s\n", message)
    	
    	enc := box.EasySeal([]byte(message), pk, sk)
    	fmt.Printf("Encrypted message: %s\n", base64.StdEncoding.EncodeToString(enc))
    	
    	dec, _ := box.EasyOpen(enc, pk, sk)
    	fmt.Printf("Decrypted message: %s\n", string(dec))
    }
    

    The result of code 1 is the following:

    Plaintext message: the sky is blue
    Encrypted message: E/QEV7B64zDkcu4+1BwJmd7juRG8cfl9NDVd/OYuC7xUWr0rkoQFOvHUsBapJqypYZAC2x71iw==
    Decrypted message: the sky is blue
    
    • Code 2:
    package main
    
    import (
    	crypto_rand "crypto/rand"
    	"encoding/base64"
    	"fmt"
    
    	"github.com/kevinburke/nacl"
    	"github.com/kevinburke/nacl/box"
    )
    
    func main() {
    	pk, sk, err := box.GenerateKey(crypto_rand.Reader)
    	if err != nil {
    		panic(err)
    	}
    	message := "the sky is blue"
    	fmt.Printf("Plaintext message: %s\n", message)
    
    	// Encrypt
    	nonce := nacl.NewNonce()
    	var out []byte
    
    	enc := box.Seal(out, []byte(message), nonce, pk, sk)
    	fmt.Printf("Encrypted message: %s\n", base64.StdEncoding.EncodeToString(enc))
    
    	// Decrypt
    	//decNonce := new([nacl.NonceSize]byte)
    	//copy(decNonce[:], message[:24])
    
    	dec, _ := box.EasyOpen(enc, pk, sk)
    	fmt.Printf("Decrypted message: %s\n", string(dec))
    }
    

    The result of code 1 is the following:

    Plaintext message: the sky is blue
    Encrypted message: KTdHagkeX6Il61uiTbCzvAqpAx4XUfr3BYhVGElPLA==
    Decrypted message: 
    

    Am I missing something when Seal() is called?

    opened by jfagoagas 0
  • More help with nonce generation in box.Easy*

    More help with nonce generation in box.Easy*

    See https://buttondown.email/cryptography-dispatches/archive/59c99d2e-9fd7-4859-934b-f52cf254e6b2 and https://github.com/golang/go/issues/43148#issuecomment-743738586.

    opened by kevinburke 0
  • Allow users to pass in their own byte arrays

    Allow users to pass in their own byte arrays

    For example, the base64 api's have a user pass in a dst array to decode into. The nacl API's in golang.org/x/crypto follow a similar pattern.

    The advantage of doing it this way is that it reduces allocations, which helps performance.

    The disadvantage is that it requires the caller to know more about how the API works, and ensure they bring along a byte array that's large enough.

    The C/C++ API's have it both ways. The C++ API's return a byte array, the C API's require you to pass one in, but I think the latter is because you can only return integers from C functions..

    opened by kevinburke 2
Owner
Kevin Burke
Formerly engineering at Twilio and Shyp. Now doing consulting, possibly for you. Get in touch!
Kevin Burke
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Jan 9, 2023
Tool for monitoring your Ethereum clients. Client-agnostic as it queries the standardized JSON-RPC APIs

e7mon Tool for monitoring your Ethereum clients. Client-agnostic as it queries the standardized JSON-RPC APIs. However, the execution client should be

null 31 Dec 20, 2022
Practicing network programming using Go. These are some fundamental APIs

Go Networking This repository is a collection of Network Programming APIs or sim

Srijan Srivastava 1 Apr 29, 2022
The minilock file encryption system, ported to pure Golang. Includes CLI utilities.

Go-miniLock A pure-Go reimplementation of the miniLock asymmetric encryption system. by Cathal Garvey, Copyright Oct. 2015, proudly licensed under the

Cathal Garvey 171 Nov 28, 2022
Pure Go Kerberos library for clients and services

gokrb5 It is recommended to use the latest version: Development will be focused on the latest major version. New features will only be targeted at thi

Jonathan Turner 621 Dec 13, 2022
Pure Go GOST cryptographic functions library.

Pure Go GOST cryptographic functions library. GOST is GOvernment STandard of Russian Federation (and Soviet Union). GOST 28147-89 (RFC 5830) block cip

Pedro Albanese 3 Aug 10, 2022
Smart.go is a pure Golang library to access disk low-level S.M.A.R.T. information

Smart.go is a pure Golang library to access disk low-level S.M.A.R.T. information. Smart.go tries to match functionality provided by smartctl but with golang API.

Anatol Pomozov 121 Dec 27, 2022
Go implementation of BLAKE2 (b) cryptographic hash function (optimized for 64-bit platforms).

Go implementation of BLAKE2b collision-resistant cryptographic hash function created by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn, an

Dmitry Chestnykh 90 Jul 11, 2022
An implementation of JOSE standards (JWE, JWS, JWT) in Go

Go JOSE Package jose aims to provide an implementation of the Javascript Object Signing and Encryption set of standards. This includes support for JSO

Square 2k Jan 8, 2023
Go implementation of SipHash-2-4, a fast short-input PRF created by Jean-Philippe Aumasson and Daniel J. Bernstein.

SipHash (Go) Go implementation of SipHash-2-4, a fast short-input PRF created by Jean-Philippe Aumasson and Daniel J. Bernstein (http://131002.net/sip

Dmitry Chestnykh 248 Dec 25, 2022
A simplified blockchain implementation in Golang

A simplified blockchain implementation in Golang

Ivan Kuznetsov 3.7k Dec 31, 2022
A full node Bitcoin (BSV) implementation written in Go

bsvd bsvd is a full node Bitcoin (BSV) implementation written in Go (golang). This project is a port of the bchd codebase to Bitcoin (BSV). It provide

null 42 Dec 25, 2022
Merchant API reference implementation

mAPI More details available in the BRFC Spec for Merchant API. The old golang (v1.1) implementation is no longer being maintained and has been moved t

Bitcoin SV 21 Dec 14, 2022
`age-plugin-yubikey` implementation, encrypt things with a Yubikey/any PIV card

This is an age plugin for PIV cards/Yubikey. Your secret is kept safe on the tamperproof hardware, while letting you use the age command-line.

Tv 22 Aug 10, 2022
Interblockchain communication protocol (IBC) implementation in Golang.

ibc-go Interblockchain communication protocol (IBC) implementation in Golang built as a SDK module. Components Core The core/ directory contains the S

COSMOS 310 Jan 7, 2023
Implementation of the Filecoin protocol, written in Go

Project Lotus - 莲 Lotus is an implementation of the Filecoin Distributed Storage Network. For more details about Filecoin, check out the Filecoin Spec

Filecoin 2.5k Jan 9, 2023
Go implementation of Ethereum proof of stake

Prysm: An Ethereum Consensus Implementation Written in Go This is the core repository for Prysm, a Golang implementation of the Ethereum Consensus spe

Prysmatic Labs 2.9k Jan 1, 2023
Go implementation of the Data At Rest Encryption (DARE) format.

Secure IO Go implementation of the Data At Rest Encryption (DARE) format. Introduction It is a common problem to store data securely - especially on u

Object Storage for the Era of the Hybrid Cloud 309 Dec 18, 2022
Celer cBridge relay node implementation in Golang

cBridge Relay Node Official implementation of cBridge relay node in Golang. Prerequisites Prepare Machine To run a cBridge relay node, it is recommend

Celer Network 62 Sep 27, 2022