title: InvalidSignature with python cryptography
body: <p>I want to verify a signature of some payload, given a public ECDSA key, and I know beforehand that the signature is correct. I want to use  the <a href="https://github.com/pyca/cryptography" rel="nofollow noreferrer">cryptography</a> python library, but the problem being, I can't make the verification work and always get a <code>InvalidSignature</code> exception, even though the signature should be correct.</p>
  
  <p>Here the code snippet I'm currently using. The public key is base64 encoded and in DER format (so no <code>---BEGIN PUBLIC KEY ---</code> etc.) and the signature is base64 encoded as well. The message is some JSON data as a string, with no spaces.</p>
  
  <pre class="lang-py prettyprint-override"><code>import base64
  from cryptography.hazmat.primitives.asymmetric import ec
  from cryptography.hazmat.primitives import serialization, hashes
  from cryptography.hazmat.backends import default_backend
  
  def cryptography_verify(signature: str, public_key: str, message: str):
      public = base64.b64decode(public_key)
      pub = serialization.load_der_public_key(public, default_backend())
  
      sig = base64.b64decode(signature)
  
      msg = bytearray(message, 'utf-8')
  
      return pub.verify(sig, msg, ec.ECDSA(hashes.SHA256()))
  </code></pre>
  
  <p>This will result in the following error.</p>
  
  <pre class="lang-py prettyprint-override"><code>Traceback (most recent call last):
    File "verify.py", line 49, in &lt;module&gt;
      test()
    File "verify.py", line 44, in test
      print(cryptography_verify(signature, public_key, message))
    File "verify.py", line 31, in cryptography_verify
      return pub.verify(sig, msg, ec.ECDSA(hashes.SHA256()))
    File "/home/philipp/.local/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/ec.py", line 352, in verify
      _ecdsa_sig_verify(self._backend, self, signature, data)
    File "/home/philipp/.local/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/ec.py", line 101, in _ecdsa_sig_verify
      raise InvalidSignature
  cryptography.exceptions.InvalidSignature
  </code></pre>
  
  <p>The reason I know the signature works for sure, is because I tried out another library called <a href="https://github.com/warner/python-ecdsa" rel="nofollow noreferrer">ecdsa</a>, where I can successfully verify the signature. Here the snippet for that.</p>
  
  <pre class="lang-py prettyprint-override"><code>import hashlib
  import base64
  import ecdsa
  
  def ecdsa_verify(signature: str, public_key: str, message: str):
      public = base64.b64decode(public_key)
      pub = ecdsa.VerifyingKey.from_der(public)
  
      sig = base64.b64decode(signature)
  
      msg = bytearray(message, 'utf-8')
  
      return pub.verify(sig, msg, hashfunc=hashlib.sha256)
  </code></pre>
  
  <p>This will just return <code>True</code>. The reason why I'm not just using the working solution is, because I have to use the <code>cryptography</code> library eventually, for some functionality that the <code>ecdsa</code> is not providing. Plus I don't want to use two libraries for the same purpose.</p>
  
  <p>After doing some digging, trying prehashing the message with no positive results, I tried printing out the public key bytes of both deserialized keys (meaning the <code>pub</code> variable).</p>
  
  <pre class="lang-py prettyprint-override"><code># for ecdsa library
  print(pub.to_string())
  
  # for cryptography library
  print(pub.public_bytes(serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo))
  </code></pre>
  
  <p>Interestingly enough, this resuts in the following.</p>
  
  <pre class="lang-py prettyprint-override"><code># for ecdsa library
  b'3Le\xf0^g\xc0\x85w \n\xee\xd4\xf7\xfc\xe5`\xa8\xe1\xc7\xd39\x0fu\x8e\x1cUi\r\xf1\x1c\xc7\x96\xe3}*\xed\x1e\x07\xfe\xd2f\x01u\x19\x05\xef\xa795\xfc\xa6\x0bf\xac\xbaS\xf8{\xbf\x1f\xbaT\x87'
  
  # for cryptography library
  b'0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\x00\x043Le\xf0^g\xc0\x85w \n\xee\xd4\xf7\xfc\xe5`\xa8\xe1\xc7\xd39\x0fu\x8e\x1cUi\r\xf1\x1c\xc7\x96\xe3}*\xed\x1e\x07\xfe\xd2f\x01u\x19\x05\xef\xa795\xfc\xa6\x0bf\xac\xbaS\xf8{\xbf\x1f\xbaT\x87'
  </code></pre>
  
  <p>Meaning the <code>cryptography</code> library prepends some bytes to the public key, in comparison to the <code>ecdsa</code> library. Why and how can I prevent this? I feel like I'm just misusing the library and this can somehow be solved, but I just don't know how.</p>
  
  <hr>
  
  <p><strong>Update1</strong>: To clarify things more, here the invocations of the verification methods. </p>
  
  <pre class="lang-py prettyprint-override"><code>def test():
      file_path = "sample.json"
      with open(file_path, "r") as file:
          file_json = json.load(file)
  
      signature = '9CMVpSkDaKUmZFoluiURVyjJGZ3GgcY1ZopPmw8qR+TsbEH2wbh4zkZDHcNzvV8MeFVn2ln5PuLv2v/+24AMSg=='
      public_key = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEM0xl8F5nwIV3IAru1Pf85WCo4cfTOQ91jhxVaQ3xHMeW430q7R4H/tJmAXUZBe+nOTX8pgtmrLpT+Hu/H7pUhw=='
      message = json.dumps(file_json, separators=(',', ':'))
  
      print(ecdsa_verify(signature, public_key, message))
      print()
      print(cryptography_verify(signature, public_key, message))
      return
  </code></pre>
  
  <p>The <code>sample.json</code> looks like this.</p>
  
  <pre><code>{
      "_type": "Targets",
      "delegations": {
          "keys": {},
          "roles": []
      },
      "expires": "2023-01-09T11:31:27.627615676+01:00",
      "targets": {
          "v1": {
              "hashes": {
                  "sha256": "E4irx6ElMoNsOoG9sAh0CbFSCPWuunqHrtz9VtY3wUU="
              },
              "length": 1994
          },
          "v2": {
              "hashes": {
                  "sha256": "uKOFIodqniVQ1YLOUaHYfr3GxXDl5YXQhWC/1kb3+AQ="
              },
              "length": 1994
          }
      },
      "version": 2
  }
  </code></pre>
  
  <p>As I understand it, both methods use the exact same inputs, so there shouldn't be any difference in the JSON message. I also hex-encoded the deserialized public keys, here you go.</p>
  
  <pre class="lang-py prettyprint-override"><code># for ecdsa
  334c65f05e67c08577200aeed4f7fce560a8e1c7d3390f758e1c55690df11cc796e37d2aed1e07fed26601751905efa73935fca60b66acba53f87bbf1fba5487
  
  # for cryptography
  3059301306072a8648ce3d020106082a8648ce3d03010703420004334c65f05e67c08577200aeed4f7fce560a8e1c7d3390f758e1c55690df11cc796e37d2aed1e07fed26601751905efa73935fca60b66acba53f87bbf1fba5487
  </code></pre>