Add google.auth.crypt (#6)
diff --git a/tests/data/other_cert.pem b/tests/data/other_cert.pem
new file mode 100644
index 0000000..6895d1e
--- /dev/null
+++ b/tests/data/other_cert.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx
+lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H
+EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL
+XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU
+RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC
+oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ
+IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW
+xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO
+ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q
+F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3
+uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB
+pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F
+mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
+b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw
+bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX
+riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS
+6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh
+CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl
+sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR
+pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N
+vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv
+/KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi
+pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7
+6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI
+nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/
+lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA==
+-----END CERTIFICATE-----
diff --git a/tests/data/pem_from_pkcs12.pem b/tests/data/pem_from_pkcs12.pem
new file mode 100644
index 0000000..2d77e10
--- /dev/null
+++ b/tests/data/pem_from_pkcs12.pem
@@ -0,0 +1,32 @@
+Bag Attributes
+ friendlyName: key
+ localKeyID: 22 7E 04 FC 64 48 20 83 1E C1 BD E3 F5 2F 44 7D EA 99 A5 BC
+Key Attributes: <No Attributes>
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDh6PSnttDsv+vi
+tUZTP1E3hVBah6PUGDWZhYgNiyW8quTWCmPvBmCR2YzuhUrY5+CtKP8UJOQico+p
+oJHSAPsrzSr6YsGs3c9SQOslBmm9Fkh9/f/GZVTVZ6u5AsUmOcVvZ2q7Sz8Vj/aR
+aIm0EJqRe9cQ5vvN9sg25rIv4xKwIZJ1VixKWJLmpCmDINqn7xvl+ldlUmSr3aGt
+w21uSDuEJhQlzO3yf2FwJMkJ9SkCm9oVDXyl77OnKXj5bOQ/rojbyGeIxDJSUDWE
+GKyRPuqKi6rSbwg6h2G/Z9qBJkqM5NNTbGRIFz/9/LdmmwvtaqCxlLtD7RVEryAp
++qTGDk5hAgMBAAECggEBAMYYfNDEYpf4A2SdCLne/9zrrfZ0kphdUkL48MDPj5vN
+TzTRj6f9s5ixZ/+QKn3hdwbguCx13QbH5mocP0IjUhyqoFFHYAWxyyaZfpjM8tO4
+QoEYxby3BpjLe62UXESUzChQSytJZFwIDXKcdIPNO3zvVzufEJcfG5no2b9cIvsG
+Dy6J1FNILWxCtDIqBM+G1B1is9DhZnUDgn0iKzINiZmh1I1l7k/4tMnozVIKAfwo
+f1kYjG/d2IzDM02mTeTElz3IKeNriaOIYTZgI26xLJxTkiFnBV4JOWFAZw15X+yR
++DrjGSIkTfhzbLa20Vt3AFM+LFK0ZoXT2dRnjbYPjQECgYEA+9XJFGwLcEX6pl1p
+IwXAjXKJdju9DDn4lmHTW0Pbw25h1EXONwm/NPafwsWmPll9kW9IwsxUQVUyBC9a
+c3Q7rF1e8ai/qqVFRIZof275MI82ciV2Mw8Hz7FPAUyoju5CvnjAEH4+irt1VE/7
+SgdvQ1gDBQFegS69ijdz+cOhFxkCgYEA5aVoseMy/gIlsCvNPyw9+Jz/zBpKItX0
+jGzdF7lhERRO2cursujKaoHntRckHcE3P/Z4K565bvVq+VaVG0T/BcBKPmPHrLmY
+iuVXidltW7Jh9/RCVwb5+BvqlwlC470PEwhqoUatY/fPJ74srztrqJHvp1L29FT5
+sdmlJW8YwokCgYAUa3dMgp5C0knKp5RY1KSSU5E11w4zKZgwiWob4lq1dAPWtHpO
+GCo63yyBHImoUJVP75gUw4Cpc4EEudo5tlkIVuHV8nroGVKOhd9/Rb5K47Hke4kk
+Brn5a0Ues9qPDF65Fw1ryPDFSwHufjXAAO5SpZZJF51UGDgiNvDedbBgMQKBgHSk
+t7DjPhtW69234eCckD2fQS5ijBV1p2lMQmCygGM0dXiawvN02puOsCqDPoz+fxm2
+DwPY80cw0M0k9UeMnBxHt25JMDrDan/iTbxu++T/jlNrdebOXFlxlI5y3c7fULDS
+LZcNVzTXwhjlt7yp6d0NgzTyJw2ju9BiREfnTiRBAoGBAOPHrTOnPyjO+bVcCPTB
+WGLsbBd77mVPGIuL0XGrvbVYPE8yIcNbZcthd8VXL/38Ygy8SIZh2ZqsrU1b5WFa
+XUMLnGEODSS8x/GmW3i3KeirW5OxBNjfUzEF4XkJP8m41iTdsQEXQf9DdUY7X+CB
+VL5h7N0VstYhGgycuPpcIUQa
+-----END PRIVATE KEY-----
diff --git a/tests/data/privatekey.p12 b/tests/data/privatekey.p12
new file mode 100644
index 0000000..c369ecb
--- /dev/null
+++ b/tests/data/privatekey.p12
Binary files differ
diff --git a/tests/data/privatekey.pem b/tests/data/privatekey.pem
new file mode 100644
index 0000000..5744354
--- /dev/null
+++ b/tests/data/privatekey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj
+7wZgkdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/
+xmVU1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYs
+SliS5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18
+pe+zpyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xk
+SBc//fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABAoIBAQDGGHzQxGKX+ANk
+nQi53v/c6632dJKYXVJC+PDAz4+bzU800Y+n/bOYsWf/kCp94XcG4Lgsdd0Gx+Zq
+HD9CI1IcqqBRR2AFscsmmX6YzPLTuEKBGMW8twaYy3utlFxElMwoUEsrSWRcCA1y
+nHSDzTt871c7nxCXHxuZ6Nm/XCL7Bg8uidRTSC1sQrQyKgTPhtQdYrPQ4WZ1A4J9
+IisyDYmZodSNZe5P+LTJ6M1SCgH8KH9ZGIxv3diMwzNNpk3kxJc9yCnja4mjiGE2
+YCNusSycU5IhZwVeCTlhQGcNeV/skfg64xkiJE34c2y2ttFbdwBTPixStGaF09nU
+Z422D40BAoGBAPvVyRRsC3BF+qZdaSMFwI1yiXY7vQw5+JZh01tD28NuYdRFzjcJ
+vzT2n8LFpj5ZfZFvSMLMVEFVMgQvWnN0O6xdXvGov6qlRUSGaH9u+TCPNnIldjMP
+B8+xTwFMqI7uQr54wBB+Poq7dVRP+0oHb0NYAwUBXoEuvYo3c/nDoRcZAoGBAOWl
+aLHjMv4CJbArzT8sPfic/8waSiLV9Ixs3Re5YREUTtnLq7LoymqB57UXJB3BNz/2
+eCueuW71avlWlRtE/wXASj5jx6y5mIrlV4nZbVuyYff0QlcG+fgb6pcJQuO9DxMI
+aqFGrWP3zye+LK87a6iR76dS9vRU+bHZpSVvGMKJAoGAFGt3TIKeQtJJyqeUWNSk
+klORNdcOMymYMIlqG+JatXQD1rR6ThgqOt8sgRyJqFCVT++YFMOAqXOBBLnaObZZ
+CFbh1fJ66BlSjoXff0W+SuOx5HuJJAa5+WtFHrPajwxeuRcNa8jwxUsB7n41wADu
+UqWWSRedVBg4Ijbw3nWwYDECgYB0pLew4z4bVuvdt+HgnJA9n0EuYowVdadpTEJg
+soBjNHV4msLzdNqbjrAqgz6M/n8Ztg8D2PNHMNDNJPVHjJwcR7duSTA6w2p/4k28
+bvvk/45Ta3XmzlxZcZSOct3O31Cw0i2XDVc018IY5be8qendDYM08icNo7vQYkRH
+504kQQKBgQDjx60zpz8ozvm1XAj0wVhi7GwXe+5lTxiLi9Fxq721WDxPMiHDW2XL
+YXfFVy/9/GIMvEiGYdmarK1NW+VhWl1DC5xhDg0kvMfxplt4tynoq1uTsQTY31Mx
+BeF5CT/JuNYk3bEBF0H/Q3VGO1/ggVS+YezdFbLWIRoMnLj6XCFEGg==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data/privatekey.pub b/tests/data/privatekey.pub
new file mode 100644
index 0000000..11fdaa4
--- /dev/null
+++ b/tests/data/privatekey.pub
@@ -0,0 +1,8 @@
+-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZg
+kdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU
+1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS
+5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+z
+pyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc/
+/fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQAB
+-----END RSA PUBLIC KEY-----
diff --git a/tests/data/public_cert.pem b/tests/data/public_cert.pem
new file mode 100644
index 0000000..7af6ca3
--- /dev/null
+++ b/tests/data/public_cert.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDIzCCAgugAwIBAgIJAMfISuBQ5m+5MA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV
+BAMTCnVuaXQtdGVzdHMwHhcNMTExMjA2MTYyNjAyWhcNMjExMjAzMTYyNjAyWjAV
+MRMwEQYDVQQDEwp1bml0LXRlc3RzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZgkdmM
+7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU1Wer
+uQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS5qQp
+gyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+zpyl4
++WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc//fy3
+ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABo3YwdDAdBgNVHQ4EFgQU2RQ8yO+O
+gN8oVW2SW7RLrfYd9jEwRQYDVR0jBD4wPIAU2RQ8yO+OgN8oVW2SW7RLrfYd9jGh
+GaQXMBUxEzARBgNVBAMTCnVuaXQtdGVzdHOCCQDHyErgUOZvuTAMBgNVHRMEBTAD
+AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBRv+M/6+FiVu7KXNjFI5pSN17OcW5QUtPr
+odJMlWrJBtynn/TA1oJlYu3yV5clc/71Vr/AxuX5xGP+IXL32YDF9lTUJXG/uUGk
++JETpKmQviPbRsvzYhz4pf6ZIOZMc3/GIcNq92ECbseGO+yAgyWUVKMmZM0HqXC9
+ovNslqe0M8C1sLm1zAR5z/h/litE7/8O2ietija3Q/qtl2TOXJdCA6sgjJX2WUql
+ybrC55ct18NKf3qhpcEkGQvFU40rVYApJpi98DiZPYFdx1oBDp/f4uZ3ojpxRVFT
+cDwcJLfNRCPUhormsY7fDS9xSyThiHsW9mjJYdcaKQkwYZ0F11yB
+-----END CERTIFICATE-----
diff --git a/tests/test__helpers.py b/tests/test__helpers.py
new file mode 100644
index 0000000..b7e0bab
--- /dev/null
+++ b/tests/test__helpers.py
@@ -0,0 +1,50 @@
+# Copyright 2016 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import pytest
+
+from google.auth import _helpers
+
+
+def test_to_bytes_with_bytes():
+ value = b'bytes-val'
+ assert _helpers.to_bytes(value) == value
+
+
+def test_to_bytes_with_unicode():
+ value = u'string-val'
+ encoded_value = b'string-val'
+ assert _helpers.to_bytes(value) == encoded_value
+
+
+def test_to_bytes_with_nonstring_type():
+ with pytest.raises(ValueError):
+ _helpers.to_bytes(object())
+
+
+def test_from_bytes_with_unicode():
+ value = u'bytes-val'
+ assert _helpers.from_bytes(value) == value
+
+
+def test_from_bytes_with_bytes():
+ value = b'string-val'
+ decoded_value = u'string-val'
+ assert _helpers.from_bytes(value) == decoded_value
+
+
+def test_from_bytes_with_nonstring_type():
+ with pytest.raises(ValueError):
+ _helpers.from_bytes(object())
diff --git a/tests/test_crypt.py b/tests/test_crypt.py
new file mode 100644
index 0000000..9069216
--- /dev/null
+++ b/tests/test_crypt.py
@@ -0,0 +1,186 @@
+# Copyright 2016 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+
+import mock
+from pyasn1_modules import pem
+import pytest
+import rsa
+import six
+
+from google.auth import _helpers
+from google.auth import crypt
+
+
+DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
+
+# To generate privatekey.pem, privatekey.pub, and public_cert.pem:
+# $ openssl req -new -newkey rsa:1024 -x509 -nodes -out public_cert.pem \
+# > -keyout privatekey.pem
+# $ openssl rsa -in privatekey.pem -pubout -out privatekey.pub
+
+with open(os.path.join(DATA_DIR, 'privatekey.pem'), 'rb') as fh:
+ PRIVATE_KEY_BYTES = fh.read()
+ PKCS1_KEY_BYTES = PRIVATE_KEY_BYTES
+
+with open(os.path.join(DATA_DIR, 'privatekey.pub'), 'rb') as fh:
+ PUBLIC_KEY_BYTES = fh.read()
+
+with open(os.path.join(DATA_DIR, 'public_cert.pem'), 'rb') as fh:
+ PUBLIC_CERT_BYTES = fh.read()
+
+# To generate other_cert.pem:
+# $ openssl req -new -newkey rsa:1024 -x509 -nodes -out other_cert.pem
+
+with open(os.path.join(DATA_DIR, 'other_cert.pem'), 'rb') as fh:
+ OTHER_CERT_BYTES = fh.read()
+
+# To generate pem_from_pkcs12.pem and privatekey.p12:
+# $ openssl pkcs12 -export -out privatekey.p12 -inkey privatekey.pem \
+# > -in public_cert.pem
+# $ openssl pkcs12 -in privatekey.p12 -nocerts -nodes \
+# > -out pem_from_pkcs12.pem
+
+with open(os.path.join(DATA_DIR, 'pem_from_pkcs12.pem'), 'rb') as fh:
+ PKCS8_KEY_BYTES = fh.read()
+
+with open(os.path.join(DATA_DIR, 'privatekey.p12'), 'rb') as fh:
+ PKCS12_KEY_BYTES = fh.read()
+
+
+def test_verify_signature():
+ to_sign = b'foo'
+ signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+ signature = signer.sign(to_sign)
+
+ assert crypt.verify_signature(
+ to_sign, signature, PUBLIC_CERT_BYTES)
+
+ # List of certs
+ assert crypt.verify_signature(
+ to_sign, signature, [OTHER_CERT_BYTES, PUBLIC_CERT_BYTES])
+
+
+def test_verify_signature_failure():
+ to_sign = b'foo'
+ signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+ signature = signer.sign(to_sign)
+
+ assert not crypt.verify_signature(
+ to_sign, signature, OTHER_CERT_BYTES)
+
+
+class TestVerifier(object):
+ def test_verify_success(self):
+ to_sign = b'foo'
+ signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+ actual_signature = signer.sign(to_sign)
+
+ verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
+ assert verifier.verify(to_sign, actual_signature)
+
+ def test_verify_unicode_success(self):
+ to_sign = u'foo'
+ signer = crypt.Signer.from_string(PRIVATE_KEY_BYTES)
+ actual_signature = signer.sign(to_sign)
+
+ verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
+ assert verifier.verify(to_sign, actual_signature)
+
+ def test_verify_failure(self):
+ verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
+ bad_signature1 = b''
+ assert not verifier.verify(b'foo', bad_signature1)
+ bad_signature2 = b'a'
+ assert not verifier.verify(b'foo', bad_signature2)
+
+ def test_from_string_pub_key(self):
+ verifier = crypt.Verifier.from_string(PUBLIC_KEY_BYTES)
+ assert isinstance(verifier, crypt.Verifier)
+ assert isinstance(verifier._pubkey, rsa.key.PublicKey)
+
+ def test_from_string_pub_key_unicode(self):
+ public_key = _helpers.from_bytes(PUBLIC_KEY_BYTES)
+ verifier = crypt.Verifier.from_string(public_key)
+ assert isinstance(verifier, crypt.Verifier)
+ assert isinstance(verifier._pubkey, rsa.key.PublicKey)
+
+ def test_from_string_pub_cert(self):
+ verifier = crypt.Verifier.from_string(PUBLIC_CERT_BYTES)
+ assert isinstance(verifier, crypt.Verifier)
+ assert isinstance(verifier._pubkey, rsa.key.PublicKey)
+
+ def test_from_string_pub_cert_unicode(self):
+ public_cert = _helpers.from_bytes(PUBLIC_CERT_BYTES)
+ verifier = crypt.Verifier.from_string(public_cert)
+ assert isinstance(verifier, crypt.Verifier)
+ assert isinstance(verifier._pubkey, rsa.key.PublicKey)
+
+ def test_from_string_pub_cert_failure(self):
+ cert_bytes = PUBLIC_CERT_BYTES
+ true_der = rsa.pem.load_pem(cert_bytes, 'CERTIFICATE')
+ with mock.patch('rsa.pem.load_pem',
+ return_value=true_der + b'extra') as load_pem:
+ with pytest.raises(ValueError):
+ crypt.Verifier.from_string(cert_bytes)
+ load_pem.assert_called_once_with(cert_bytes, 'CERTIFICATE')
+
+
+class TestSigner(object):
+ def test_from_string_pkcs1(self):
+ signer = crypt.Signer.from_string(PKCS1_KEY_BYTES)
+ assert isinstance(signer, crypt.Signer)
+ assert isinstance(signer._key, rsa.key.PrivateKey)
+
+ def test_from_string_pkcs1_unicode(self):
+ key_bytes = _helpers.from_bytes(PKCS1_KEY_BYTES)
+ signer = crypt.Signer.from_string(key_bytes)
+ assert isinstance(signer, crypt.Signer)
+ assert isinstance(signer._key, rsa.key.PrivateKey)
+
+ def test_from_string_pkcs8(self):
+ signer = crypt.Signer.from_string(PKCS8_KEY_BYTES)
+ assert isinstance(signer, crypt.Signer)
+ assert isinstance(signer._key, rsa.key.PrivateKey)
+
+ def test_from_string_pkcs8_extra_bytes(self):
+ key_bytes = PKCS8_KEY_BYTES
+ _, pem_bytes = pem.readPemBlocksFromFile(
+ six.StringIO(_helpers.from_bytes(key_bytes)),
+ crypt._PKCS8_MARKER)
+
+ with mock.patch('pyasn1.codec.der.decoder.decode') as mock_decode:
+ key_info, remaining = None, 'extra'
+ mock_decode.return_value = (key_info, remaining)
+ with pytest.raises(ValueError):
+ crypt.Signer.from_string(key_bytes)
+ # Verify mock was called.
+ mock_decode.assert_called_once_with(
+ pem_bytes, asn1Spec=crypt._PKCS8_SPEC)
+
+ def test_from_string_pkcs8_unicode(self):
+ key_bytes = _helpers.from_bytes(PKCS8_KEY_BYTES)
+ signer = crypt.Signer.from_string(key_bytes)
+ assert isinstance(signer, crypt.Signer)
+ assert isinstance(signer._key, rsa.key.PrivateKey)
+
+ def test_from_string_pkcs12(self):
+ with pytest.raises(ValueError):
+ crypt.Signer.from_string(PKCS12_KEY_BYTES)
+
+ def test_from_string_bogus_key(self):
+ key_bytes = 'bogus-key'
+ with pytest.raises(ValueError):
+ crypt.Signer.from_string(key_bytes)