aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst7
-rw-r--r--docs/hazmat/primitives/mac/poly1305.rst45
-rw-r--r--src/cryptography/hazmat/primitives/poly1305.py12
-rw-r--r--tests/hazmat/primitives/test_poly1305.py27
4 files changed, 91 insertions, 0 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 9ece6d1d..2421efee 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -8,6 +8,13 @@ Changelog
.. note:: This version is not yet released and is under active development.
+* Added class methods
+ :meth:`Poly1305.generate_tag
+ <cryptography.hazmat.primitives.poly1305.Poly1305.generate_tag>`
+ and
+ :meth:`Poly1305.verify_tag
+ <cryptography.hazmat.primitives.poly1305.Poly1305.verify_tag>`
+ for Poly1305 sign and verify operations.
* Deprecated support for OpenSSL 1.0.1. Support will be removed in
``cryptography`` 2.9.
* We now ship ``manylinux2010`` wheels in addition to our ``manylinux1``
diff --git a/docs/hazmat/primitives/mac/poly1305.rst b/docs/hazmat/primitives/mac/poly1305.rst
index 1d0753c6..7504a076 100644
--- a/docs/hazmat/primitives/mac/poly1305.rst
+++ b/docs/hazmat/primitives/mac/poly1305.rst
@@ -85,3 +85,48 @@ messages allows an attacker to forge tags. Poly1305 is described in
:return bytes: The message authentication code as bytes.
:raises cryptography.exceptions.AlreadyFinalized:
+
+ .. classmethod:: generate_tag(key, data)
+
+ A single step alternative to do sign operations. Returns the message
+ authentication code as ``bytes`` for the given ``key`` and ``data``.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :return bytes: The message authentication code as bytes.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+ :raises TypeError: This exception is raised if ``key`` or ``data`` are
+ not ``bytes``.
+
+ .. doctest::
+
+ >>> poly1305.Poly1305.generate_tag(key, b"message to authenticate")
+ b'T\xae\xff3\xbdW\xef\xd5r\x01\xe2n=\xb7\xd2h'
+
+ .. classmethod:: verify_tag(key, data, tag)
+
+ A single step alternative to do verify operations. Securely compares the
+ MAC to ``tag``, using the given ``key`` and ``data``.
+
+ :param key: Secret key as ``bytes``.
+ :type key: :term:`bytes-like`
+ :param data: The bytes to hash and authenticate.
+ :type data: :term:`bytes-like`
+ :param bytes tag: The bytes to compare against.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the version of OpenSSL ``cryptography`` is compiled against does not
+ support this algorithm.
+ :raises TypeError: This exception is raised if ``key``, ``data`` or
+ ``tag`` are not ``bytes``.
+ :raises cryptography.exceptions.InvalidSignature: If tag does not match.
+
+ .. doctest::
+
+ >>> poly1305.Poly1305.verify_tag(key, b"message to authenticate", b"an incorrect tag")
+ Traceback (most recent call last):
+ ...
+ cryptography.exceptions.InvalidSignature: Value did not match computed tag.
diff --git a/src/cryptography/hazmat/primitives/poly1305.py b/src/cryptography/hazmat/primitives/poly1305.py
index 02b6629d..d92f62ad 100644
--- a/src/cryptography/hazmat/primitives/poly1305.py
+++ b/src/cryptography/hazmat/primitives/poly1305.py
@@ -41,3 +41,15 @@ class Poly1305(object):
ctx, self._ctx = self._ctx, None
ctx.verify(tag)
+
+ @classmethod
+ def generate_tag(cls, key, data):
+ p = Poly1305(key)
+ p.update(data)
+ return p.finalize()
+
+ @classmethod
+ def verify_tag(cls, key, data, tag):
+ p = Poly1305(key)
+ p.update(data)
+ p.verify(tag)
diff --git a/tests/hazmat/primitives/test_poly1305.py b/tests/hazmat/primitives/test_poly1305.py
index 71495ff7..edca4623 100644
--- a/tests/hazmat/primitives/test_poly1305.py
+++ b/tests/hazmat/primitives/test_poly1305.py
@@ -47,6 +47,9 @@ class TestPoly1305(object):
poly.update(msg)
assert poly.finalize() == tag
+ assert Poly1305.generate_tag(key, msg) == tag
+ Poly1305.verify_tag(key, msg, tag)
+
def test_key_with_no_additional_references(self, backend):
poly = Poly1305(os.urandom(32))
assert len(poly.finalize()) == 16
@@ -66,6 +69,9 @@ class TestPoly1305(object):
with pytest.raises(TypeError):
poly.update(u'')
+ with pytest.raises(TypeError):
+ Poly1305.generate_tag(b"0" * 32, u'')
+
def test_verify(self, backend):
poly = Poly1305(b"0" * 32)
poly.update(b"msg")
@@ -78,6 +84,8 @@ class TestPoly1305(object):
poly2.update(b"msg")
poly2.verify(tag)
+ Poly1305.verify_tag(b"0" * 32, b"msg", tag)
+
def test_invalid_verify(self, backend):
poly = Poly1305(b"0" * 32)
poly.update(b"msg")
@@ -89,22 +97,37 @@ class TestPoly1305(object):
with pytest.raises(InvalidSignature):
p2.verify(b"\x00" * 16)
+ with pytest.raises(InvalidSignature):
+ Poly1305.verify_tag(b"0" * 32, b"msg", b"\x00" * 16)
+
def test_verify_reject_unicode(self, backend):
poly = Poly1305(b"0" * 32)
with pytest.raises(TypeError):
poly.verify(u'')
+ with pytest.raises(TypeError):
+ Poly1305.verify_tag(b"0" * 32, b"msg", u'')
+
def test_invalid_key_type(self, backend):
with pytest.raises(TypeError):
Poly1305(object())
+ with pytest.raises(TypeError):
+ Poly1305.generate_tag(object(), b"msg")
+
def test_invalid_key_length(self, backend):
with pytest.raises(ValueError):
Poly1305(b"0" * 31)
with pytest.raises(ValueError):
+ Poly1305.generate_tag(b"0" * 31, b"msg")
+
+ with pytest.raises(ValueError):
Poly1305(b"0" * 33)
+ with pytest.raises(ValueError):
+ Poly1305.generate_tag(b"0" * 33, b"msg")
+
def test_buffer_protocol(self, backend):
key = binascii.unhexlify(
b"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cb"
@@ -123,3 +146,7 @@ class TestPoly1305(object):
assert poly.finalize() == binascii.unhexlify(
b"4541669a7eaaee61e708dc7cbcc5eb62"
)
+
+ assert Poly1305.generate_tag(key, msg) == binascii.unhexlify(
+ b"4541669a7eaaee61e708dc7cbcc5eb62"
+ )