Example #1
0
func ExampleCipher() {
	key, err := hex.DecodeString("60143a3d7c7137c3622d490e7dbb85859138d198d9c648960e186412a6250722")
	if err != nil {
		panic(err)
	}

	// A nonce should only be used once. Generate it randomly.
	nonce, err := hex.DecodeString("308c92676fa95973")
	if err != nil {
		panic(err)
	}

	c, err := chacha20.New(key, nonce)
	if err != nil {
		panic(err)
	}

	src := []byte("hello I am a secret message")
	dst := make([]byte, len(src))

	c.XORKeyStream(dst, src)

	fmt.Printf("%x\n", dst)
	// Output:
	// a05452ebd981422dcdab2c9cde0d20a03f769e87d3e976ee6d6a11
}
Example #2
0
func TestBadNonceSize(t *testing.T) {
	key := make([]byte, chacha20.KeySize)
	nonce := make([]byte, 3)

	_, err := chacha20.New(key, nonce)

	if err != chacha20.ErrInvalidNonce {
		t.Error("Should have rejected an invalid nonce")
	}
}
// generateCipherStream generates a stream of cryptographic psuedo-random bytes
// intened to be used to encrypt a message using a one-time-pad like
// construciton.
func generateCipherStream(key [keyLen]byte, numBytes uint) []byte {
	var nonce [8]byte
	cipher, err := chacha20.New(key[:], nonce[:])
	if err != nil {
		panic(err)
	}
	output := make([]byte, numBytes)
	cipher.XORKeyStream(output, output)

	return output
}
Example #4
0
// Test how and if de-/encoding works with chacha20 - surprise it works
func TestChacha20(t *testing.T) {
	K, _ := hex.DecodeString("6a3bfd77d9efac53f8ef51712796bf7a37541f425a5dc5397c8a2c3c040d9301")
	message, _ := hex.DecodeString("8e685bd3237866e7a424b0f33df1a087a397a78e147042d2d17b159044d2ad1162dea13df2a119b61c90d62fc76335f49954557f2b07c463dca1664ca042599fca66068b16bc3e7e1896536ca2")

	c, err := chacha20.New(K, []byte("PS-Msg05"))
	if err != nil {
		t.Fatal(err)
	}

	var out = make([]byte, len(message))
	c.XORKeyStream(out, message)

	c2, err := chacha20.New(K, []byte("PS-Msg05"))
	if err != nil {
		t.Fatal(err)
	}

	var out2 = make([]byte, len(message))
	c2.XORKeyStream(out2, out)
	if reflect.DeepEqual(out2, message) == false {
		t.Fatal(out2)
	}
}
Example #5
0
func main() {
	fmt.Println("[")

	// 5 tests
	for i := 0; i < 5; i++ {
		plaintext := make([]byte, 64)
		rand.Read(plaintext)

		key := make([]byte, 32)
		rand.Read(key)

		nonce := make([]byte, 8)
		rand.Read(nonce)

		stream, _ := chacha20.New(key[:], nonce)

		e32a := make([]byte, 32)
		var pkey [32]byte
		stream.XORKeyStream(pkey[:], e32a)

		ciphertext := make([]byte, 64)
		stream.XORKeyStream(ciphertext, plaintext)

		var tag [16]byte
		poly1305.Sum(&tag, ciphertext, &pkey)

		fmt.Printf(`	{
		key: new Buffer([
%s		]),
		nonce: new Buffer([
%s		]),
		plain: new Buffer([
%s		]),
		cipher: new Buffer([
%s		]),
		tag: new Buffer([
%s		]),
	},
`,
			hexify(key, "\t\t\t"),
			hexify(nonce, "\t\t\t"),
			hexify(plaintext, "\t\t\t"),
			hexify(ciphertext, "\t\t\t"),
			hexify(tag[:], "\t\t\t"),
		)
	}

	fmt.Println("]")
}
Example #6
0
// DecryptAndVerify returns the chacha20 decrypted messages.
// An error is returned when the poly1305 message authenticator (seal) could not be verified.
// Nonce should be 8 byte.
func DecryptAndVerify(key, nonce, message []byte, mac [16]byte, add []byte) ([]byte, error) {

	chacha20, err := chacha20.New(key, nonce)
	if err != nil {
		panic(err)
	}

	// poly1305 key is chacha20 over 32 zeros
	var poly1305Key [32]byte
	var chacha20KeyOut = make([]byte, 64)
	var zeros = make([]byte, 64)
	chacha20.XORKeyStream(chacha20KeyOut, zeros)
	copy(poly1305Key[:], chacha20KeyOut)

	var chacha20Out = make([]byte, len(message))
	var poly1305Out [16]byte

	// poly1305 byte order
	// - add bytes up to mod 16 (if available)
	// - message up to mod 16
	// - number of add bytes up to mod 8
	// - number of message bytes up to mod 8
	var poly1305In []byte
	if len(add) > 0 {
		poly1305In = AddBytes(poly1305In, add, 16)
	}

	poly1305In = AddBytes(poly1305In, message, 16)
	addLength := make([]byte, 8)
	msgLength := make([]byte, 8)
	binary.LittleEndian.PutUint64(addLength, uint64(len(add)))
	binary.LittleEndian.PutUint64(msgLength, uint64(len(message)))

	poly1305In = AddBytes(poly1305In, addLength, 8)
	poly1305In = AddBytes(poly1305In, msgLength, 8)

	poly1305.Sum(&poly1305Out, poly1305In, &poly1305Key)

	if poly1305.Verify(&mac, poly1305In, &poly1305Key) == false {
		return nil, errors.New("MAC not equal: " + hex.EncodeToString(poly1305Out[:]) + " != " + hex.EncodeToString(mac[:]))
	}

	chacha20.XORKeyStream(chacha20Out, message)
	return chacha20Out, nil
}
Example #7
0
func TestChaCha20(t *testing.T) {
	for i, vector := range testVectors {
		if vector.rounds == 20 {
			t.Logf("Running test vector %d", i)

			key, err := hex.DecodeString(vector.key)
			if err != nil {
				t.Error(err)
			}

			nonce, err := hex.DecodeString(vector.nonce)
			if err != nil {
				t.Error(err)
			}

			c, err := chacha20.New(key, nonce)
			if err != nil {
				t.Error(err)
			}

			expected, err := hex.DecodeString(vector.keyStream)
			if err != nil {
				t.Error(err)
			}

			src := make([]byte, len(expected))
			dst := make([]byte, len(expected))
			c.XORKeyStream(dst, src)

			if !bytes.Equal(expected, dst) {
				t.Errorf("Bad keystream: expected %x, was %x", expected, dst)

				for i, v := range expected {
					if dst[i] != v {
						t.Logf("Mismatch at offset %d: %x vs %x", i, v, dst[i])
						break
					}
				}
			}
		}
	}
}
Example #8
0
// EncryptAndSeal returns the chacha20 encrypted message and poly1305 message authentictor (also refered as seals)
// Nonce should be 8 byte
func EncryptAndSeal(key, nonce, message []byte, add []byte) ([]byte /*encrypted*/, [16]byte /*mac*/, error) {

	chacha20, err := chacha20.New(key, nonce)
	if err != nil {
		panic(err)
	}

	// poly1305 key is chacha20 over 32 zeros
	var poly1305Key [32]byte
	var chacha20KeyOut = make([]byte, 64)
	var zeros = make([]byte, 64)
	chacha20.XORKeyStream(chacha20KeyOut, zeros)
	copy(poly1305Key[:], chacha20KeyOut)

	var chacha20Out = make([]byte, len(message))
	var poly1305Out [16]byte
	chacha20.XORKeyStream(chacha20Out, message)

	var poly1305In []byte
	if len(add) > 0 {
		poly1305In = AddBytes(poly1305In, add, 16)
	}

	poly1305In = AddBytes(poly1305In, chacha20Out, 16)
	addLength := make([]byte, 8)
	msgLength := make([]byte, 8)
	binary.LittleEndian.PutUint64(addLength, uint64(len(add)))
	binary.LittleEndian.PutUint64(msgLength, uint64(len(message)))

	poly1305In = AddBytes(poly1305In, addLength, 8)
	poly1305In = AddBytes(poly1305In, msgLength, 8)

	poly1305.Sum(&poly1305Out, poly1305In, &poly1305Key)

	return chacha20Out, poly1305Out, nil
}
Example #9
0
func newChaCha20Stream(key, iv []byte, _ DecOrEnc) (cipher.Stream, error) {
	return chacha20.New(key, iv)
}
Example #10
0
func BenchmarkChaCha20(b *testing.B) {
	key := make([]byte, chacha20.KeySize)
	nonce := make([]byte, chacha20.NonceSize)
	c, _ := chacha20.New(key, nonce)
	benchmarkStream(b, c)
}
Example #11
0
func chacha20XOR(nonce []byte, dst []byte, src []byte) {
	chacha20Cipher, _ := chacha20.New(secretKey, nonce)
	chacha20Cipher.XORKeyStream(dst, src)
}