GithubHelp home page GithubHelp logo

latchset / jwcrypto Goto Github PK

View Code? Open in Web Editor NEW
426.0 426.0 119.0 726 KB

Implements JWK,JWS,JWE specifications using python-cryptography

License: GNU Lesser General Public License v3.0

Python 99.80% Makefile 0.20%

jwcrypto's People

Contributors

andrewmackie avatar ashb avatar atombrella avatar cclauss avatar cito avatar clemux avatar codedust avatar dabrado avatar david-homelend avatar deftez avatar dijonkitchen avatar enugentdt avatar jamesgardiner avatar jcgruenhage avatar jonathanhuot avatar lumjjb avatar mbaldwin avatar myrual avatar peppelinux avatar pmarillo avatar pmeerw avatar puiterwijk avatar simo5 avatar simonw avatar spilikin avatar swattu avatar synkc avatar thomas-mollard avatar tiran avatar tirkarthi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jwcrypto's Issues

Not passing a protected header when creating a compact JWE causes KeyError

Minimal test case:

# testcase.py
from jwcrypto.jwe import JWE
from jwcrypto.jwk import JWK

payload = "some payload text"

jwe = JWE(payload)

key = JWK.generate(kty='RSA', size=4096)

header = {
    "alg": "RSA-OAEP-256",
    "enc": "A256CBC-HS512",
    "typ": "JWE",
}

jwe.add_recipient(key, header)

serialised = jwe.serialize(compact=True)
$ python testcase.py
Traceback (most recent call last):
  File "testcase.py", line 18, in <module>
    serialised = jwe.serialize(compact=True)
  File "/home/michael/code/jwcrypto/jwcrypto/jwe.py", line 285, in serialize
    ph = json_decode(self.objects['protected'])
KeyError: 'protected'

It seems like this is a fairly easy fix to initialise the 'protected' key in 'objects' to {}, but I'm not sure if this is allowed by the JWE spec?

Version API

It would probably be very useful to have a public version number (either API version or the normal package version, although API version might be more useful).
This is mostly because when new arguments are added to existing function (example: private_only for JWKSet.export), it would be good to be able to find out if one can use it with the currently installed version.
Normally you would say "I need at least version X", but I don't think that the convenience this once function gives is worth the requirement in my opinion.

So an (API) version would be useful.

Registered claim names check

Saw what you did here
https://github.com/simo5/custodia/blob/master/custodia/message/kem.py#L103

I make a simple code to check every reserved claim mentioned in RFC7519.

def check_claims(claims, audience, issuer, issue_time, subject, jti, leeway=int()):
    try:
        if claims['aud'] != audience:
            return 'audience does not match'
    except KeyError:
        return 'missing intended audience in payload'

    try:
        if claims['nbf'] > time.time():
            return 'message is not activated yet'
    except KeyError:
        return 'missing activation time in payload'

    try:
        if claims['exp'] < time.time() + leeway:
            return 'message has expired'
    except KeyError:
        return 'missing expiration time in payload'

    try:
        if claims['iss'] != issuer:
            return 'issuer does not match'
    except KeyError:
        return 'missing issuer in payload'

    try:
        if claims['sub'] != subject:
            return 'subject does not match'
    except KeyError:
        return 'missing subject description in payload'

    try:
        if claims['iat'] != int(issue_time):
            return 'issue time does not match'
    except KeyError:
        return 'missing issue time in payload'

    try:
        if claims['jti'] != int(jti):
            return 'token id does not match'
    except KeyError:
        return 'missing token in payload'

    return True

another version based on what is in the claim

def check_claims(claims, audience=str(), issuer=str(),
                 issue_time=int(), subject=str(),
                 token_id=int(), leeway=int()):
    if 'aud' in claims and claims['aud'] != audience:
        return 'audience does not match'
    elif 'nbf' in claims and claims['nbf'] > time.time():
        return 'message is not activated yet'
    elif 'exp' in claims and claims['exp'] < time.time() + leeway:
        return 'message has expired'
    elif 'iss' in claims and claims['iss'] != issuer:
        return 'issuer does not match'
    elif 'sub' in claims and claims['sub'] != subject:
        return 'subject does not match'
    elif 'iat' in claims and claims['iat'] != int(issue_time):
        return 'issue time does not match'
    elif 'jti' in claims and claims['jti'] != int(token_id):
        return 'token id does not match'
    else:
        return True

JWE API feedback

First of all thanks for an excellent library. I'm using the library for JWE de/encryption in combination with square/js-jose.

It took me a while to figure out the API and what I ended up with is:

def encrypt(plaintext, public_jwk)
    protected = '{"alg":"RSA-OAEP","enc":"A256GCM"}'
    jwe = JWE(plaintext=plaintext, protected=protected)
    jwe.add_recipient(public_jwk)
    ciphertext = jwe.serialize(compact=True)
    return ciphertext

def decrypt(ciphertext, private_jwk):
    jwe = JWE()
    jwe.deserialize(ciphertext, key=private_jwk)
    plaintext = jwe.payload.decode('utf-8')
    return plaintext

Unfortunately those two functions look very different and aren't at all symmetric. If this is at all reasonable code, I found a couple of things non-obvious:

  • The protected header could use an example in the docs. Otherwise you have to read large parts of the RFC to understand what it means.
  • The protected argument to JWE is a string, I'd expected it to be a Python dict and assumed the API would take care of the conversion internally.
  • It would be nice if there would be a key argument to JWE.__init__ adding a default recipient. Since I use compact encoding, there can only be a single recipient and this would avoid the extra call to add_recipient.
  • The JWE.deserialize function notes that it destroys the entire JWE state. Wouldn't it make more sense to change this into a class or staticmethod which internally creates a new JWE instance?
  • JWE.deserialize has no return value. I expected it to return the plaintext and not get it from the payload property.

This is all well meant feedback after I used the library for a single purpose, so I might very well be missing larger implications or context.

Thanks! Hanno

export individual public or private key?

When I generate a key-pair with:

k = jwk.JWK(generate='EC', crv='P-256', use='enc', kid='9876543210')

I'd like to "export" the public key in json format to communicate it to other parties. My understanding from reading the example code and API was, that I could possibly do that with:

pk = k.get_op_key('encrypt')
pk_json = pk.export()

but that doesn't work: "AttributeError: '_EllipticCurvePublicKey' object has no attribute 'export'"

Couldn't find any explicit example of this in the test code. Maybe I am missing something?
Thanks for the help - Frank.

size type confusion

jwcrypto sometimes uses bits and sometimes bytes for key size, e.g. JWK(generate='oct') takes size in bits, jwe._direct.wrap() reports InvalidCEKeyLength in bytes. Please stick to either bits or bytes.

CVE-2016-6298: Million Messages Attack vulnerability

The jwcrypto implementation of the RSA1_5 algorithm is vulnerable to the Million Message Attack described in RFC 3128.

A timing attack can be leveraged against the implementation to detect when a chosed ciphertext generates a valid header and padding because invalid headr/padding generates a code exception and cryptographic operations are terminated earlier resulting in measurably faster processing over the network.

Many thanks to Dennis Detering [email protected] for discovering and reporting this vulnerability.

Utility functions for importing key files on disk?

A pretty standard use of this library is dealing with key files which need to be serialized/deserialized to disk. The JWK objects should either expose a constructor which can initialize them from on-disk PEM files, or else maybe some utility functionality should be provided to make this available?

A good middle-ground would be allowing directly initializing JWK's from rsa.Cryptography objects, since internally this is done anyway with functions like JWK._rsa_pri

consider re-license or dual Apache v2.0

LGPLv3 may be incompatible with Apache v2.0. See:

rubychan/coderay#25
https://softwareengineering.stackexchange.com/questions/81947/why-is-jquery-released-under-mit-and-not-lgpl

Maybe even do dual Apache v2.0/MIT like the Rust community sfackler/rust-postgres-macros#19

Also just fyi to give you scope, jwcrypto was downloaded via pip 3473 times in the last 30 days.

bigquery

SELECT                                            
  details.installer.name as installer_name,       
  COUNT(*) as download_count,                     
FROM                                              
  TABLE_DATE_RANGE(                               
    [the-psf:pypi.downloads],                     
    DATE_ADD(CURRENT_TIMESTAMP(), -31, "day"),    
    DATE_ADD(CURRENT_TIMESTAMP(), -1, "day")      
  )                                               
WHERE                                             
  file.project = "jwcrypto"                       
GROUP BY                                          
  installer_name,                                 
ORDER BY                                          
  download_count DESC                             
LIMIT 20                                          

export symmetric key?

Trying to find a way to export the symmetric key as jose-json after:

sym_k = jwk.JWK(generate='oct', size=256, use='sig', kid = '24680')

sym_k.export() throws an exception:

...
UnicodeDecodeError: 'utf8' codec can't decode byte 0xd6 in position 2: invalid continuation byte
...

while the sym_k.get_op_key('sign') seems to return the key's random byte-array.

Any advise?

Encrypt with RSA-OAEP-256 public key

Hello,
Sorry about question in issues. I am not sure does it a bug or my mistake.

Fedora 24, python 3.5, jwcrypto 0.3 from pip

I generated RSA with WebCrypto

var rsaKey;

window.crypto.subtle.generateKey(
    {
        name: "RSA-OAEP",
        modulusLength: 2048, //can be 1024, 2048, or 4096
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
    },
    true, //whether the key is extractable (i.e. can be used in exportKey)
    ["encrypt", "decrypt"] //must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
)
.then(function(key){
    rsaKey = key;
})
.catch(function(err){
    console.error(err);
});

and exported public key to Python

rsa_pub = {'kty': 'RSA', 'key_ops': ['encrypt'], 'e': 'AQAB', 'ext': True, 
           'alg': 'RSA-OAEP-256', 
           'n': '3buQYV0Ba82vbi0tbzAxG50WzSqZkOiUc7mKb6wyxwebg_laPYN04umK4a2hVgi318kp_ItQiZaBpqmxOXmVLnn62bWDuHdCeEaFBpy8oFzNRwhVPMw-c97t3Xj-m6sEHSAuTKxjsj429gjHF0cHFpxUe1HQ6Z61Ubz9v1lFEBKAcY33e_p-odH86k0NdnnG6L0wQKyyf6XJcATehwGbiXk5KxgSZIKdh_2WfsNEN5FArr_JLevo9gDu87RH8uJxoqct5s99iNK2AdjW83eqzlBlLX4491oJdMwZwRSeyllqqJvSEoM3_vgXES9ylHJsbYzqMYHeC1B2QOtzcUH85Q'}

I trying to use it with jwcrypto for encryption some data

key = jwk.JWK(**rsa_pub)
header = json.dumps({'enc': 'A256GCM', 'alg': 'RSA-OAEP-256'})

j = jwe.JWE(b'some_data')
j.add_recipient(key, header)

I got and exception

Traceback (most recent call last):
  File "/home/kozlov-o/SOURCES/Python/Projects/Python3/LFR/lfr_root/crypto.py", line 37, in <module>
    j.add_recipient(key, header)
  File "/home/kozlov-o/SOURCES/Python/Projects/Python3/LFR/venv/lib/python3.5/site-packages/jwcrypto/jwe.py", line 978, in add_recipient
    wrapped = alg.wrap(key, enc.key_size, self.cek, jh)
  File "/home/kozlov-o/SOURCES/Python/Projects/Python3/LFR/venv/lib/python3.5/site-packages/jwcrypto/jwe.py", line 169, in wrap
    rk = key.get_op_key('wrapKey')
  File "/home/kozlov-o/SOURCES/Python/Projects/Python3/LFR/venv/lib/python3.5/site-packages/jwcrypto/jwk.py", line 532, in get_op_key
    self._check_constraints('enc', operation)
  File "/home/kozlov-o/SOURCES/Python/Projects/Python3/LFR/venv/lib/python3.5/site-packages/jwcrypto/jwk.py", line 453, in _check_constraints
    raise InvalidJWKOperation(operation, ops)
jwcrypto.jwk.InvalidJWKOperation: Invalid operation requested: "Encrypt key". Valid for: "['Encrypt content']"

I tried to create header with every value from jwe.default_allowed_algs in for 'enc' key. Always exception.

What I do wrong? Target is to generate private and public keys on client and encrypt some data with client's public key on server.

Best Regards,
Oleg

Implement missing JWE algorithms

draft-ietf-jose-json-web-algorithms-40
4.6. Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES)
4.7. Key Encryption with AES GCM
4.8. Key Encryption with PBES2

Test invalid curve points

Add test cases to verify that we handle invalid curve points correctly. @simo5 was brave enough to jump head-first into OpenSSL. It looks like we are safe. Let's add some tests to be sure.

in cryptography load_elliptic_curve_public_numbers() calls _ec_key_set_public_key_affine_coordinates()
in that function EC_KEY_set_public_key_affine_coordinates() is called from openssl
and inside openssl the last function called in the method is: EC_KEY_check_key()
jose calls EC_KEY_check_key() too

setup.py doesn't mention cryptography as a requirement

I notice that you have cryptography in requirements.txt but not in setup.py, so when installing this module JWK related function won't work.

Was this a concious decision so that people could use the JWT functions without needing a harder-to-install module or is there some other reason? If it's this I'll happily open a small PR to add a comment in the docs, or otherwise open one to add install_requires to setup.py

Verification not working against WebCrypto keys

This might as well be some large fuckup of mine.

What I did:

  1. used WebCrypto to generate a keypair.
const keyOptions = {name: "ECDSA", namedCurve: "P-256"}
const signOptions = {name: "ECDSA", hash: {name: "SHA-256"}}
  1. exported the public key as JWK:
{"crv":"P-256","ext":true,"key_ops":["verify"],"kty":"EC","x":"kudpCZSQcYKDOVlYAxfVyZc6NhPFKB2I6-3-Q14leqE","y":"MTynqg8ZTf2eKZ-YKsgGFg35S88De5wz5Tol4YMujHc"}
  1. took a trivial challenge, "a", converted it to a new Uint8Array([ 97 ]) and signed with the private key. Got the following signature:
tOdwela6LqWd6S3acKgLKAX6VXNb3NcDN1v6RR0/nGa1t/eF6OZTSU6puq2px9r815kA4XrW5oOZDYxNL+VdAQ==
  1. loaded the exported public key in Python:
key = jwk.JWK(**decoded_public_key)
  1. created a JWS token:
sig = jws.JWS()
  1. tried to verify the signature:
>>> sig.deserialize('{"payload":"YQ==", "signature":"tOdwela6LqWd6S3acKgLKAX6VXNb3NcDN1v6RR0/nGa1t/eF6OZTSU6puq2px9r815kA4XrW5oOZDYxNL+VdAQ=="}', key, "ES256")
  1. got the InvalidSignature() exception.

Is there something I am doing fundamentally incorrect?

JWS signature header type mismatch

To pass a header to JWS.add_signature I need to encode it has a string otherwise an exception it raised:

header = {..}
jws.add_signature(key, header=header)
# Raises TypeError
jws.add_signature(key, header=json_encode(header))
# Sucess

This results in the signature contain the decoding header with in the JSM object.

When a 'verify' is performed the header is passed as is to _verify where json_decode(header) is called and the following error occurs:

InvalidJWSSignature: Verification failed for all signatures['Failed: [TypeError("the JSON object must be str, not \'dict\'",)]'] 

If I skip the decode in ``_verify` the verify succeeds. Should the string'ified header be added to the signature object?

Give some examples

Is it possible to add some quick examples to demonstrate how to establish a JWT or JWS in the document?
It will be great to see JWS and JWE in action in the same time.

JWT bad check for the nbf claim

When decoding a token that has the nbf claim set the library fails to decode it with:

(...)
File "(...)/.tox/env/lib/python2.7/site-packages/jwcrypto/jwt.py", line 343, in _check_default_claims
    self._check_exp(claims['nbf'], time.time(), self._leeway)
File "(...)/.tox/env/lib/python2.7/site-packages/jwcrypto/jwt.py", line 323, in _check_exp
claim, limit, leeway))
JWTExpired: Expired at 1480353842, time: 1480353902(leeway: 60)

Which refers to this line:

self._check_exp(claims['nbf'], time.time(), self._leeway)

self._check_exp(claims['nbf'], time.time(), self._leeway)

As you can see, the nbf is checked using the _check_exp(), I think it should be checked using the _check_nbf():

def _check_nbf(self, claim, limit, leeway):

Thanks

'JWK' has no attribute 'generate'

I have tried as example, both python 2 and 3, and it throws:

key = jwk.JWK.generate(kty='oct', size=256)
Traceback (most recent call last):
File "", line 1, in
AttributeError: type object 'JWK' has no attribute 'generate'

Dictionary Interface for JWK

JWK should have a dict-like interface. You should be able to get, set and delete. Bonus points if JWK inherits from dict.

Use common base class for exceptions

All jwcrypto exceptions should have a common base class. It makes it easier to except and handle all jwcrypto exceptions in application code.

JWK import error and patch.

Hi, I ran into the following....

jwk = JWK(**{
   ...:       "cmt": "Some comment.....",
   ...:       "crv": "P-256",
   ...:       "d": "M6GNqEwYbrdlsOd1H0oP9YrzHdpUXPzZ83x5s3FCp_Y",
   ...:       "kid": "fRI11S2Z1-rp_8Y-4HBAgbH2tTVFUhPE1WWShaxkvxg",
   ...:       "kty": "EC",
   ...:       "size": 256,
   ...:       "x": "ZTYFLm2Z7f3OM6sMNaXPlKksj6l8bv92fJwO253HVys",
   ...:       "y": "vqHIwT8kcCG4-4vkgYTWd5rLqfEtXeRdUVAEyg-LZKk"
   ...:     })

InvalidJWKValue: Unknown key parameters: ['size']

size is valid, cmt is "unknown". Removing cmt or size succeeds but the real problem is removing from a list while iterating it. The following patch allows unknown names, like 'cmt'. The assert is
there to test.

diff --git a/jwcrypto/jwk.py b/jwcrypto/jwk.py
--- a/jwcrypto/jwk.py
+++ b/jwcrypto/jwk.py
@@ -286,13 +286,12 @@ class JWK(object):

         # Unknown key parameters are allowed
         # Let's just store them out of the way
-        for name in names:
+        for name in list(names):
             self._unknown[name] = kwargs[name]
             while name in names:
                 names.remove(name)

-        if len(names) != 0:
-            raise InvalidJWKValue('Unknown key parameters: %s' % names)
+        assert(len(names) == 0)

         if len(self._key) == 0:
             raise InvalidJWKValue('No Key Values found')

-travis

JWK.get_curve('P-256') fails with KeyError

Example:

>>>> from jwcrypto import jwk
>>>> k = jwk.JWK(generate='EC', curve='P-256')
>>>> k.get_curve('P-256')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/ldb/virtualenvs/Amsonia/site-packages/jwcrypto/jwk.py", line 358, in get_curve
    if arg and k['crv'] != arg:
KeyError: 'crv'
>>>> 

So, it appears that 'crv': 'P-256' is not added to the JWK's _key dict when the object is created.

Lack of doc to install it under python3

It seem default is python2, you need to run : sudo apt-get install python3-jwcrypto instead

otherwise, in python3:

from jwcrypto import jwk, jws
Traceback (most recent call last):
File "", line 1, in
ImportError: No module named 'jwcrypto'

KeyboardInterrupt

Making all the exceptions inherit from JWException

It seems like this is just something that was missed out by accident? It would be nice if all the exceptions for JWE/JWT/etc. inherited from JWException in common.py so they could be caught in one except block.

JWKSet doesn't allow for other keys

The RFC explicitly allows the use of other key/value pairs in the JWKSet object. However, the library doesn't allow this. JWKSet should probably just implement the dict interface instead of the set interface.

Import/Export consistency

The export() methods should return a python dictionary that can be passed to json.dumpf(). Likewise, the import() methods should take a python dictionary as returned from json.loadf(). Please don't do the encoding internal to the API.

Is there a way to use custom key for encryption/decryption?

I'm trying to use this library but in my use case we load keys from our own key store.

The problem is how would I create a JWK object to represent a key? I can see that I can generate a new key, o load it from PEM file, but that doesn't work for me. I would like to pass a string/byte array containing the key. Is that possible?

jwcrypto 0.3.0 breaks FreeIPA

The latest release of jwcrypto breaks FreeIPA's ipa-replica-install. ipareplica-install log on the new replica:

2016-08-15T16:28:04Z DEBUG Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/ipaserver/install/service.py", line 447, in start_creation
    run_step(full_msg, method)
  File "/usr/lib/python2.7/site-packages/ipaserver/install/service.py", line 437, in run_step
    method()
  File "/usr/lib/python2.7/site-packages/ipaserver/install/custodiainstance.py", line 98, in __import_ra_key
    cli.fetch_key('ra/ipaCert')
  File "/usr/lib/python2.7/site-packages/ipapython/secrets/client.py", line 92, in fetch_key
    r.raise_for_status()
  File "/usr/lib/python2.7/site-packages/requests/models.py", line 844, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
HTTPError: 406 Client Error: Failed to validate message: Key ID is None, should be a SPN for url: https://master.ipa.example/ipa/keys/ra/ipaCert?type=kem&va
lue=eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwia2lkIjpudWxsfQ.ijUrXfBZulqVjDRlpkgIWUuWnLQfXDQzo2vx1kRFd1M_EejwPAOptONv9hgVVWs1tvuUt4Ix3MIi1ZF-lB1g0
MSaHcE65gWciJlQDC5PcihRIT3YQMVaW2AnYh7RCQIpOM3Rz_GH08NCjguIk1Q4tHKq_Yqo6XjhcrxuTSdOBCA_9eAfvyj6GBH1oy_2z54ZkPd1G5ztCZh1C2BPRHRlpBxxQj4ooVvX7RWPHmq_lri2NWzU2
8_B5mybcvOKkegu-w6thsPb0Pg4AeY_rxPlD5hjBmN_S5dCMkM4IVjtLn_nZkCi9NbN_Y8hONaJ7ljeR8e2Mo0ypXxGqYRPnYt3XQ.9zYMjMvDk0QGfiPAFU5bGQ.Hjof2y5DysgzhHRK4xad26yuDJx5LBD
uWgdd79yxPtbUqRCyYZR-rfkzJqk2iTalgNbw-f3BhNqBwptBIHxYirCFzh-ndN_ooOQEeAVRfPBOS6Z5M5ALgEt8VK6_1IEYd5SsS7EF_ZT7kHniKJozBhzpGchciQ4aMoskZdNX_2BYvyDgg_pVo54hB-B
y2XOJ0kZJbHiZ_VoKDmkqvUmjvvVSemoYJw2tytC7ygze_c76O2vs-EKv8nivLlxQDuhQ65rZl89_QZR4rFhhs9A6WlakBgUszBUUS5MdRvCQPEJEIGuXZKF_nxFZkcicz_RxGB5jmJK61UuXNTQJ9SgG5HI
Z7oG5yW5-4ZX_rVun71q1ZvBNN_zmlVCl8YSx0xGxbaGINkbCH7dXOYOXLiYLurUFcAMAE7DQjiO3GFhoTSd6EFq9EpM5MKUDzRGtuqLUJqemrrzSxZQ3CBo0aLqQlkfe0LeZ9vrx2-zXv-0cxpDA-csFqNb
C5HxFzGJl4LVlF-kUe7wbBbrlHHx7qQ1m7QqhuUPbjTNsoUIsx0hCILXKHEmER6ftuG6ARJo47EAZ.r-coYU-7udAB-YdOoZWg-flLDOwlo0SCSkk6dTburJY

I added a couple of print statements to custodia on the master and ran

$ sudo -u apache curl -H 'GSS_NAME: admin' --unix /run/httpd/ipa-custodia.sock 'http://localhost/keys/ra/ipaCert?...
...
Aug 15 17:07:16 master.ipa.example custodia[11695]: <jwcrypto.jwe.JWE object at 0x7f8d49482890> {u'alg': u'RSA1_5', u'enc': u'A256CBC-HS512', u'kid': None}
Aug 15 17:07:16 master.ipa.example custodia[11695]: <jwcrypto.jws.JWS object at 0x7f8d4fe83410> {u'alg': u'RS256', u'kid': None}

kid is both None for the inner and outer object.

base64url_encode() should return "bytes"

In common.py, the function base64url_encode() seems to be a convenience function that accepts both bytes and unicode-strings, utf8-encodes the latter, base64URLsafe encodes the bytes, strips any padding of trailing "=", and utf8-decodes the result to a unicode-string, which is returned.

However, base64 encoding should return bytes...

I can understand that you want a convenience function that returns a unicode-string such that you can easily assign it to a python object or attribute for json encoding later, but maybe rename the function to base64url_encode2ustr() or something like that to differentiate it from pure base64 encoding.

(sorry to be pedantic about this, but all this bytes vs str vs unicode in python2 vs python3 with all the inconsistent unicode/b64/json-encoding is so f#$%^ed up that keeping it clear seems to be the only way to keep ones sanity ;-) )

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.