diff --git a/libp2p/crypto/chacha20poly1305.nim b/libp2p/crypto/chacha20poly1305.nim
index fc09a2b68..bdc9a8458 100644
--- a/libp2p/crypto/chacha20poly1305.nim
+++ b/libp2p/crypto/chacha20poly1305.nim
@@ -23,7 +23,7 @@ const
ChaChaPolyTagSize = 16
type
- ChaChaPoly = object
+ ChaChaPoly* = object
ChaChaPolyKey* = array[ChaChaPolyKeySize, byte]
ChaChaPolyNonce* = array[ChaChaPolyNonceSize, byte]
ChaChaPolyTag* = array[ChaChaPolyTagSize, byte]
diff --git a/libp2p/crypto/curve25519.nim b/libp2p/crypto/curve25519.nim
new file mode 100644
index 000000000..a9a18c2b1
--- /dev/null
+++ b/libp2p/crypto/curve25519.nim
@@ -0,0 +1,82 @@
+## Nim-Libp2p
+## Copyright (c) 2020 Status Research & Development GmbH
+## Licensed under either of
+## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
+## * MIT license ([LICENSE-MIT](LICENSE-MIT))
+## at your option.
+## This file may not be copied, modified, or distributed except according to
+## those terms.
+
+## This module integrates BearSSL ChaCha20+Poly1305
+##
+## This module uses unmodified parts of code from
+## BearSSL library
+## Copyright(C) 2018 Thomas Pornin .
+
+# RFC @ https://tools.ietf.org/html/rfc7748
+
+import bearssl
+
+const
+ Curve25519KeySize = 32
+
+type
+ Curve25519* = object
+ Curve25519Key* = array[Curve25519KeySize, byte]
+ pcuchar = ptr cuchar
+
+
+const
+ ForbiddenCurveValues: array[12, Curve25519Key] = [
+ [0.byte, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1.byte, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [224.byte, 235, 122, 124, 59, 65, 184, 174, 22, 86, 227, 250, 241, 159, 196, 106, 218, 9, 141, 235, 156, 50, 177, 253, 134, 98, 5, 22, 95, 73, 184, 0],
+ [95.byte, 156, 149, 188, 163, 80, 140, 36, 177, 208, 177, 85, 156, 131, 239, 91, 4, 68, 92, 196, 88, 28, 142, 134, 216, 34, 78, 221, 208, 159, 17, 87],
+ [236.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127],
+ [237.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127],
+ [238.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127],
+ [205.byte, 235, 122, 124, 59, 65, 184, 174, 22, 86, 227, 250, 241, 159, 196, 106, 218, 9, 141, 235, 156, 50, 177, 253, 134, 98, 5, 22, 95, 73, 184, 128],
+ [76.byte, 156, 149, 188, 163, 80, 140, 36, 177, 208, 177, 85, 156, 131, 239, 91, 4, 68, 92, 196, 88, 28, 142, 134, 216, 34, 78, 221, 208, 159, 17, 215],
+ [217.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+ [218.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+ [219.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 25],
+ ]
+
+let defaultBrEc = brEcGetDefault()
+
+proc mul*(_: type[Curve25519], dst: var Curve25519Key, scalar: Curve25519Key, point: Curve25519Key) =
+ # The source point is provided in array G (of size Glen bytes);
+ # the multiplication result is written over it.
+ dst = scalar
+ let
+ res = defaultBrEc.mul(
+ cast[pcuchar](addr dst[0]),
+ Curve25519KeySize,
+ cast[pcuchar](unsafeAddr point[0]),
+ Curve25519KeySize,
+ EC_curve25519.cint)
+ assert res == 1
+
+proc mulgen*(_: type[Curve25519], dst: var Curve25519Key, scalar: Curve25519Key) =
+ while true:
+ let
+ size = defaultBrEc.mulgen(
+ cast[pcuchar](addr dst[0]),
+ cast[pcuchar](unsafeAddr scalar[0]),
+ Curve25519KeySize,
+ EC_curve25519.cint)
+ assert size == Curve25519KeySize
+ for forbid in ForbiddenCurveValues:
+ if dst == forbid:
+ continue
+ break
+
+when isMainModule:
+ var
+ key: Curve25519Key
+ dst: Curve25519Key
+ dst2: Curve25519Key
+ Curve25519.mulgen(dst, key)
+ echo dst
+ Curve25519.mul(dst2, dst, key)
+ echo dst2