170 lines
4.1 KiB
Go
170 lines
4.1 KiB
Go
|
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
|
||
|
// Use of this source code is governed by a license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"golang.org/x/crypto/chacha20poly1305"
|
||
|
)
|
||
|
|
||
|
func HChaCha20(out *[32]byte, nonce []byte, key *[32]byte) {
|
||
|
|
||
|
v00 := uint32(0x61707865)
|
||
|
v01 := uint32(0x3320646e)
|
||
|
v02 := uint32(0x79622d32)
|
||
|
v03 := uint32(0x6b206574)
|
||
|
|
||
|
v04 := binary.LittleEndian.Uint32(key[0:])
|
||
|
v05 := binary.LittleEndian.Uint32(key[4:])
|
||
|
v06 := binary.LittleEndian.Uint32(key[8:])
|
||
|
v07 := binary.LittleEndian.Uint32(key[12:])
|
||
|
v08 := binary.LittleEndian.Uint32(key[16:])
|
||
|
v09 := binary.LittleEndian.Uint32(key[20:])
|
||
|
v10 := binary.LittleEndian.Uint32(key[24:])
|
||
|
v11 := binary.LittleEndian.Uint32(key[28:])
|
||
|
v12 := binary.LittleEndian.Uint32(nonce[0:])
|
||
|
v13 := binary.LittleEndian.Uint32(nonce[4:])
|
||
|
v14 := binary.LittleEndian.Uint32(nonce[8:])
|
||
|
v15 := binary.LittleEndian.Uint32(nonce[12:])
|
||
|
|
||
|
for i := 0; i < 20; i += 2 {
|
||
|
v00 += v04
|
||
|
v12 ^= v00
|
||
|
v12 = (v12 << 16) | (v12 >> 16)
|
||
|
v08 += v12
|
||
|
v04 ^= v08
|
||
|
v04 = (v04 << 12) | (v04 >> 20)
|
||
|
v00 += v04
|
||
|
v12 ^= v00
|
||
|
v12 = (v12 << 8) | (v12 >> 24)
|
||
|
v08 += v12
|
||
|
v04 ^= v08
|
||
|
v04 = (v04 << 7) | (v04 >> 25)
|
||
|
v01 += v05
|
||
|
v13 ^= v01
|
||
|
v13 = (v13 << 16) | (v13 >> 16)
|
||
|
v09 += v13
|
||
|
v05 ^= v09
|
||
|
v05 = (v05 << 12) | (v05 >> 20)
|
||
|
v01 += v05
|
||
|
v13 ^= v01
|
||
|
v13 = (v13 << 8) | (v13 >> 24)
|
||
|
v09 += v13
|
||
|
v05 ^= v09
|
||
|
v05 = (v05 << 7) | (v05 >> 25)
|
||
|
v02 += v06
|
||
|
v14 ^= v02
|
||
|
v14 = (v14 << 16) | (v14 >> 16)
|
||
|
v10 += v14
|
||
|
v06 ^= v10
|
||
|
v06 = (v06 << 12) | (v06 >> 20)
|
||
|
v02 += v06
|
||
|
v14 ^= v02
|
||
|
v14 = (v14 << 8) | (v14 >> 24)
|
||
|
v10 += v14
|
||
|
v06 ^= v10
|
||
|
v06 = (v06 << 7) | (v06 >> 25)
|
||
|
v03 += v07
|
||
|
v15 ^= v03
|
||
|
v15 = (v15 << 16) | (v15 >> 16)
|
||
|
v11 += v15
|
||
|
v07 ^= v11
|
||
|
v07 = (v07 << 12) | (v07 >> 20)
|
||
|
v03 += v07
|
||
|
v15 ^= v03
|
||
|
v15 = (v15 << 8) | (v15 >> 24)
|
||
|
v11 += v15
|
||
|
v07 ^= v11
|
||
|
v07 = (v07 << 7) | (v07 >> 25)
|
||
|
v00 += v05
|
||
|
v15 ^= v00
|
||
|
v15 = (v15 << 16) | (v15 >> 16)
|
||
|
v10 += v15
|
||
|
v05 ^= v10
|
||
|
v05 = (v05 << 12) | (v05 >> 20)
|
||
|
v00 += v05
|
||
|
v15 ^= v00
|
||
|
v15 = (v15 << 8) | (v15 >> 24)
|
||
|
v10 += v15
|
||
|
v05 ^= v10
|
||
|
v05 = (v05 << 7) | (v05 >> 25)
|
||
|
v01 += v06
|
||
|
v12 ^= v01
|
||
|
v12 = (v12 << 16) | (v12 >> 16)
|
||
|
v11 += v12
|
||
|
v06 ^= v11
|
||
|
v06 = (v06 << 12) | (v06 >> 20)
|
||
|
v01 += v06
|
||
|
v12 ^= v01
|
||
|
v12 = (v12 << 8) | (v12 >> 24)
|
||
|
v11 += v12
|
||
|
v06 ^= v11
|
||
|
v06 = (v06 << 7) | (v06 >> 25)
|
||
|
v02 += v07
|
||
|
v13 ^= v02
|
||
|
v13 = (v13 << 16) | (v13 >> 16)
|
||
|
v08 += v13
|
||
|
v07 ^= v08
|
||
|
v07 = (v07 << 12) | (v07 >> 20)
|
||
|
v02 += v07
|
||
|
v13 ^= v02
|
||
|
v13 = (v13 << 8) | (v13 >> 24)
|
||
|
v08 += v13
|
||
|
v07 ^= v08
|
||
|
v07 = (v07 << 7) | (v07 >> 25)
|
||
|
v03 += v04
|
||
|
v14 ^= v03
|
||
|
v14 = (v14 << 16) | (v14 >> 16)
|
||
|
v09 += v14
|
||
|
v04 ^= v09
|
||
|
v04 = (v04 << 12) | (v04 >> 20)
|
||
|
v03 += v04
|
||
|
v14 ^= v03
|
||
|
v14 = (v14 << 8) | (v14 >> 24)
|
||
|
v09 += v14
|
||
|
v04 ^= v09
|
||
|
v04 = (v04 << 7) | (v04 >> 25)
|
||
|
}
|
||
|
|
||
|
binary.LittleEndian.PutUint32(out[0:], v00)
|
||
|
binary.LittleEndian.PutUint32(out[4:], v01)
|
||
|
binary.LittleEndian.PutUint32(out[8:], v02)
|
||
|
binary.LittleEndian.PutUint32(out[12:], v03)
|
||
|
binary.LittleEndian.PutUint32(out[16:], v12)
|
||
|
binary.LittleEndian.PutUint32(out[20:], v13)
|
||
|
binary.LittleEndian.PutUint32(out[24:], v14)
|
||
|
binary.LittleEndian.PutUint32(out[28:], v15)
|
||
|
}
|
||
|
|
||
|
func XChaCha20Poly1305Encrypt(
|
||
|
dst []byte,
|
||
|
nonceFull *[24]byte,
|
||
|
plaintext []byte,
|
||
|
additionalData []byte,
|
||
|
key *[chacha20poly1305.KeySize]byte,
|
||
|
) []byte {
|
||
|
var nonce [chacha20poly1305.NonceSize]byte
|
||
|
var derivedKey [chacha20poly1305.KeySize]byte
|
||
|
HChaCha20(&derivedKey, nonceFull[:16], key)
|
||
|
aead, _ := chacha20poly1305.New(derivedKey[:])
|
||
|
copy(nonce[4:], nonceFull[16:])
|
||
|
return aead.Seal(dst, nonce[:], plaintext, additionalData)
|
||
|
}
|
||
|
|
||
|
func XChaCha20Poly1305Decrypt(
|
||
|
dst []byte,
|
||
|
nonceFull *[24]byte,
|
||
|
plaintext []byte,
|
||
|
additionalData []byte,
|
||
|
key *[chacha20poly1305.KeySize]byte,
|
||
|
) ([]byte, error) {
|
||
|
var nonce [chacha20poly1305.NonceSize]byte
|
||
|
var derivedKey [chacha20poly1305.KeySize]byte
|
||
|
HChaCha20(&derivedKey, nonceFull[:16], key)
|
||
|
aead, _ := chacha20poly1305.New(derivedKey[:])
|
||
|
copy(nonce[4:], nonceFull[16:])
|
||
|
return aead.Open(dst, nonce[:], plaintext, additionalData)
|
||
|
}
|