16
16
17
17
package fr .acinq .eclair .crypto
18
18
19
- import java .nio .ByteOrder
20
-
21
19
import fr .acinq .bitcoin .{ByteVector32 , Protocol }
22
20
import fr .acinq .eclair .crypto .ChaCha20Poly1305 .{DecryptionError , EncryptionError , InvalidCounter }
23
- import grizzled .slf4j .Logger
24
21
import grizzled .slf4j .Logging
25
- import org .spongycastle .crypto .engines .ChaCha7539Engine
26
- import org .spongycastle .crypto .params .{KeyParameter , ParametersWithIV }
22
+ import org .bouncycastle .crypto .engines .ChaCha7539Engine
23
+ import org .bouncycastle .crypto .params .{KeyParameter , ParametersWithIV }
27
24
import scodec .bits .ByteVector
28
25
26
+ import java .nio .ByteOrder
27
+
29
28
/**
30
- * Poly1305 authenticator
31
- * see https://tools.ietf.org/html/rfc7539#section-2.5
32
- */
29
+ * Poly1305 authenticator
30
+ * see https://tools.ietf.org/html/rfc7539#section-2.5
31
+ */
33
32
object Poly1305 {
34
33
/**
35
- *
36
- * @param key input key
37
- * @param datas input data
38
- * @return a 16 byte authentication tag
39
- */
34
+ * @param key input key
35
+ * @param datas input data
36
+ * @return a 16 byte authentication tag
37
+ */
40
38
def mac (key : ByteVector , datas : ByteVector * ): ByteVector = {
41
39
val out = new Array [Byte ](16 )
42
- val poly = new org.spongycastle .crypto.macs.Poly1305 ()
40
+ val poly = new org.bouncycastle .crypto.macs.Poly1305 ()
43
41
poly.init(new KeyParameter (key.toArray))
44
42
datas.foreach(data => poly.update(data.toArray, 0 , data.length.toInt))
45
43
poly.doFinal(out, 0 )
@@ -48,13 +46,10 @@ object Poly1305 {
48
46
}
49
47
50
48
/**
51
- * ChaCha20 block cipher
52
- * see https://tools.ietf.org/html/rfc7539#section-2.5
53
- */
49
+ * ChaCha20 block cipher
50
+ * see https://tools.ietf.org/html/rfc7539#section-2.5
51
+ */
54
52
object ChaCha20 {
55
- // Whenever key rotation happens, we start with a nonce value of 0 and increment it for each message.
56
- val ZeroNonce = ByteVector .fill(12 )(0 .byteValue)
57
-
58
53
def encrypt (plaintext : ByteVector , key : ByteVector , nonce : ByteVector , counter : Int = 0 ): ByteVector = {
59
54
val engine = new ChaCha7539Engine ()
60
55
engine.init(true , new ParametersWithIV (new KeyParameter (key.toArray), nonce.toArray))
@@ -91,65 +86,50 @@ object ChaCha20 {
91
86
}
92
87
93
88
/**
94
- * ChaCha20Poly1305 AEAD (Authenticated Encryption with Additional Data) algorithm
95
- * see https://tools.ietf.org/html/rfc7539#section-2.5
96
- *
97
- * This what we should be using (see BOLT #8)
98
- */
89
+ * ChaCha20Poly1305 AEAD (Authenticated Encryption with Additional Data) algorithm
90
+ * see https://tools.ietf.org/html/rfc7539#section-2.5
91
+ *
92
+ * This what we should be using (see BOLT #8)
93
+ */
99
94
object ChaCha20Poly1305 extends Logging {
100
95
96
+ // @formatter:off
101
97
abstract class ChaCha20Poly1305Error (msg : String ) extends RuntimeException (msg)
102
98
case class InvalidMac () extends ChaCha20Poly1305Error (" invalid mac" )
103
99
case class DecryptionError () extends ChaCha20Poly1305Error (" decryption error" )
104
100
case class EncryptionError () extends ChaCha20Poly1305Error (" encryption error" )
105
101
case class InvalidCounter () extends ChaCha20Poly1305Error (" chacha20 counter must be 0 or 1" )
106
-
107
- // This logger is used to dump encryption keys to enable traffic analysis by the lightning-dissector.
108
- // See https://github.com/nayutaco/lightning-dissector for more details.
109
- // It is disabled by default (in the logback.xml configuration file).
110
- val keyLogger = Logger (" keylog" )
102
+ // @formatter:on
111
103
112
104
/**
113
- *
114
- * @param key 32 bytes encryption key
115
- * @param nonce 12 bytes nonce
116
- * @param plaintext plain text
117
- * @param aad additional authentication data. can be empty
118
- * @return a (ciphertext, mac) tuple
119
- */
105
+ * @param key 32 bytes encryption key
106
+ * @param nonce 12 bytes nonce
107
+ * @param plaintext plain text
108
+ * @param aad additional authentication data. can be empty
109
+ * @return a (ciphertext, mac) tuple
110
+ */
120
111
def encrypt (key : ByteVector , nonce : ByteVector , plaintext : ByteVector , aad : ByteVector ): (ByteVector , ByteVector ) = {
121
112
val polykey = ChaCha20 .encrypt(ByteVector32 .Zeroes , key, nonce)
122
113
val ciphertext = ChaCha20 .encrypt(plaintext, key, nonce, 1 )
123
114
val tag = Poly1305 .mac(polykey, aad, pad16(aad), ciphertext, pad16(ciphertext), Protocol .writeUInt64(aad.length, ByteOrder .LITTLE_ENDIAN ), Protocol .writeUInt64(ciphertext.length, ByteOrder .LITTLE_ENDIAN ))
124
-
125
115
logger.debug(s " encrypt( $key, $nonce, $aad, $plaintext) = ( $ciphertext, $tag) " )
126
- if (nonce === ChaCha20 .ZeroNonce ) {
127
- keyLogger.debug(s " ${tag.toHex} ${key.toHex}" )
128
- }
129
-
130
116
(ciphertext, tag)
131
117
}
132
118
133
119
/**
134
- *
135
- * @param key 32 bytes decryption key
136
- * @param nonce 12 bytes nonce
137
- * @param ciphertext ciphertext
138
- * @param aad additional authentication data. can be empty
139
- * @param mac authentication mac
140
- * @return the decrypted plaintext if the mac is valid.
141
- */
120
+ * @param key 32 bytes decryption key
121
+ * @param nonce 12 bytes nonce
122
+ * @param ciphertext ciphertext
123
+ * @param aad additional authentication data. can be empty
124
+ * @param mac authentication mac
125
+ * @return the decrypted plaintext if the mac is valid.
126
+ */
142
127
def decrypt (key : ByteVector , nonce : ByteVector , ciphertext : ByteVector , aad : ByteVector , mac : ByteVector ): ByteVector = {
143
128
val polykey = ChaCha20 .encrypt(ByteVector32 .Zeroes , key, nonce)
144
129
val tag = Poly1305 .mac(polykey, aad, pad16(aad), ciphertext, pad16(ciphertext), Protocol .writeUInt64(aad.length, ByteOrder .LITTLE_ENDIAN ), Protocol .writeUInt64(ciphertext.length, ByteOrder .LITTLE_ENDIAN ))
145
130
if (tag != mac) throw InvalidMac ()
146
131
val plaintext = ChaCha20 .decrypt(ciphertext, key, nonce, 1 )
147
-
148
132
logger.debug(s " decrypt( $key, $nonce, $aad, $ciphertext, $mac) = $plaintext" )
149
- if (nonce === ChaCha20 .ZeroNonce ) {
150
- keyLogger.debug(s " ${mac.toHex} ${key.toHex}" )
151
- }
152
-
153
133
plaintext
154
134
}
155
135
0 commit comments