hideki nara avatar hideki nara committed dbec39b

plain,jws,jwe token classes

Comments (0)

Files changed (14)

docs/source/conf.py

 html_theme = 'haiku'
 exclude_patterns = [ 'jwt/*.rst','jwe/*.rst','jws/*.rst','jwk/*.rst',
                 ]
-
+todo_include_todos = True

docs/source/jwe.rst

 
 Based on draft-jones-json-web-encryption-02( http://self-issued.info/docs/draft-jones-json-web-encryption.html)
 
+.. todo::
 
-(December 13, 2011)
+    (December 13, 2011)
 
 
 .. _jwe.abstract:

docs/source/jwt.rst

 `JSON Web Token (JWT) draft-jones-json-web-token-06 <http://self-issued.info/docs/draft-jones-json-web-token.html>`_ 
 (October 30, 2011 )
 
-
 .. todo::
     Now draft is 07 (December 13, 2011)
     ( http://self-issued.info/docs/draft-jones-json-web-token.html )

docs/source/jwt/12.1.rst

 12.1. Normative References
 ------------------------------------------
 
-[JWS]   Jones, M., Balfanz, D., Bradley, J., Goland, Y., Panzer, J., Sakimura, N., and P. Tarjan, “JSON Web Signature (JWS),” October 2011.
-[RFC2045]   Freed, N. and N. Borenstein, “Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies,” RFC 2045, November 1996 (TXT).
-[RFC2119]   Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels,” BCP 14, RFC 2119, March 1997 (TXT, HTML, XML).
-[RFC3339]   Klyne, G., Ed. and C. Newman, “Date and Time on the Internet: Timestamps,” RFC 3339, July 2002 (TXT, HTML, XML).
-[RFC3629]   Yergeau, F., “UTF-8, a transformation format of ISO 10646,” STD 63, RFC 3629, November 2003 (TXT).
-[RFC3986]   Berners-Lee, T., Fielding, R., and L. Masinter, “Uniform Resource Identifier (URI): Generic Syntax,” STD 66, RFC 3986, January 2005 (TXT, HTML, XML).
-[RFC4627]   Crockford, D., “The application/json Media Type for JavaScript Object Notation (JSON),” RFC 4627, July 2006 (TXT).
-[RFC4648]   Josefsson, S., “The Base16, Base32, and Base64 Data Encodings,” RFC 4648, October 2006 (TXT).
-[RFC5226]   Narten, T. and H. Alvestrand, “Guidelines for Writing an IANA Considerations Section in RFCs,” BCP 26, RFC 5226, May 2008 (TXT).
-[USA15] Davis, M., Whistler, K., and M. Dürst, “Unicode Normalization Forms,” Unicode Standard Annex 15, 09 2009.
+
+.. glossary::
+
+    JWS 
+           Jones, M., Balfanz, D., Bradley, J., Goland, Y., Panzer, J., Sakimura, N., and P. Tarjan, “JSON Web Signature (JWS),” October 2011.
+           (:doc:`jws`)
+
+    RFC2045
+           Freed, N. and N. Borenstein, “Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies,” RFC 2045, November 1996 (TXT).
+
+    RFC2119
+           Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels,” BCP 14, RFC 2119, March 1997 (TXT, HTML, XML).
+
+    RFC3339
+           Klyne, G., Ed. and C. Newman, “Date and Time on the Internet: Timestamps,” RFC 3339, July 2002 (TXT, HTML, XML).
+
+    RFC3629
+           Yergeau, F., “UTF-8, a transformation format of ISO 10646,” STD 63, RFC 3629, November 2003 (TXT).
+
+    RFC3986
+           Berners-Lee, T., Fielding, R., and L. Masinter, “Uniform Resource Identifier (URI): Generic Syntax,” STD 66, RFC 3986, January 2005 (TXT, HTML, XML).
+
+    RFC4627
+           Crockford, D., “The application/json Media Type for JavaScript Object Notation (JSON),” RFC 4627, July 2006 (TXT).
+
+    RFC4648
+           Josefsson, S., “The Base16, Base32, and Base64 Data Encodings,” RFC 4648, October 2006 (TXT).
+
+    RFC5226
+           Narten, T. and H. Alvestrand, “Guidelines for Writing an IANA Considerations Section in RFCs,” BCP 26, RFC 5226, May 2008 (TXT).
+
+    USA15
+         Davis, M., Whistler, K., and M. Dürst, “Unicode Normalization Forms,” Unicode Standard Annex 15, 09 2009.
 
 (v.06)

docs/source/jwt/12.2.rst

 12.2. Informative References
 ----------------------------------------
 
-[CanvasApp] Facebook, “Canvas Applications,” 2010.
-[JSS]   Bradley, J. and N. Sakimura (editor), “JSON Simple Sign,” September 2010.
-[JWE]   Jones, M., Rescorla, E., and J. Hildebrand, “JSON Web Encryption (JWE),” October 2011.
-[MagicSignatures]   Panzer (editor), J., Laurie, B., and D. Balfanz, “Magic Signatures,” August 2010.
-[OASIS.saml-core-2.0-os]    Cantor, S., Kemp, J., Philpott, R., and E. Maler, “Assertions and Protocol for the OASIS Security Assertion Markup Language (SAML) V2.0,” OASIS Standard saml-core-2.0-os, March 2005.
-[RFC3275]   Eastlake, D., Reagle, J., and D. Solo, “(Extensible Markup Language) XML-Signature Syntax and Processing,” RFC 3275, March 2002 (TXT).
-[RFC4122]   Leach, P., Mealling, M., and R. Salz, “A Universally Unique IDentifier (UUID) URN Namespace,” RFC 4122, July 2005 (TXT, HTML, XML).
-[SWT]   Hardt, D. and Y. Goland, “Simple Web Token (SWT),” Version 0.9.5.1, November 2009.
-[W3C.CR-xml11-20021015] Cowan, J., “Extensible Markup Language (XML) 1.1,” W3C CR CR-xml11-20021015, October 2002.
+.. glossary::
+
+    CanvasApp
+         Facebook, “Canvas Applications,” 2010.
+
+    JSS
+           Bradley, J. and N. Sakimura (editor), “JSON Simple Sign,” September 2010.
+
+    JWE
+           Jones, M., Rescorla, E., and J. Hildebrand, “JSON Web Encryption (JWE),” October 2011. (:doc:`jwe`)
+
+    MagicSignatures
+           Panzer (editor), J., Laurie, B., and D. Balfanz, “Magic Signatures,” August 2010.
+
+    OASIS.saml-core-2.0-os
+            Cantor, S., Kemp, J., Philpott, R., and E. Maler, “Assertions and Protocol for the OASIS Security Assertion Markup Language (SAML) V2.0,” OASIS Standard saml-core-2.0-os, March 2005.
+
+    RFC3275
+           Eastlake, D., Reagle, J., and D. Solo, “(Extensible Markup Language) XML-Signature Syntax and Processing,” RFC 3275, March 2002 (TXT).
+
+    RFC4122
+           Leach, P., Mealling, M., and R. Salz, “A Universally Unique IDentifier (UUID) URN Namespace,” RFC 4122, July 2005 (TXT, HTML, XML).
+
+    SWT
+           Hardt, D. and Y. Goland, “Simple Web Token (SWT),” Version 0.9.5.1, November 2009.
+
+    W3C.CR-xml11-20021015
+         Cowan, J., “Extensible Markup Language (XML) 1.1,” W3C CR CR-xml11-20021015, October 2002.
 
 (v.06)

docs/source/jwt/7.rst

 7.  Rules for Creating and Validating a JWT
 ====================================================
 
+.. note::
+    - :doc:`jws` : [:term:`Encoded JWS Header`].[:term:`Encoded JWS Payload`].[:term:`Encoded JWS Signature`] 
+    - :doc:`jwe` - [:term:`Encoded JWE Header`].[:term:`Encoded JWE Encrypted Key`].[:term:`Encoded JWE Ciphertext`] 
+    - **plaintext** - [:term:`Encoded JWT Header`].[:term:`Message`] 
+
+.. glossary::
+    Message
+         UTF-8 representation of the :term:`JWT Claims Object`
+
 To create a JWT, one MUST follow these steps:
 
-    1.  Create a JWT Claims Object containing the desired claims. 
-        Note that white space is explicitly allowed in the representation and no canonicalization is performed before encoding.
+    1.  Create a :term:`JWT Claims Object` containing the desired claims. 
+        Note that :term:`white space` is explicitly allowed in the representation 
+        and no canonicalization is performed before encoding.
+
+    2.  Let the :term:`Message` be the bytes of the UTF-8 representation of the :term:`JWT Claims Object`.
 
-    2.  Let the Message be the bytes of the UTF-8 representation of the JWT Claims Object.
+    3.  Create a :term:`JWT Header` containing the desired set of header parameters. 
 
-    3.  Create a JWT Header containing the desired set of header parameters. 
         If the JWT is to be signed or encrypted, 
-        they MUST conform to either the [JWS] or [JWE] specifications, respectively. 
-        Else, if the JWT is to be plaintext, 
-        the alg value none MUST be used. 
-        Note that white space is explicitly allowed in the representation 
+        they MUST conform to either the [:term:`JWS`] or [:term:`JWE`] specifications, respectively. 
+
+        Else, if the JWT is to be :term:`plaintext`, 
+        the :term:`alg` value **none** MUST be used. 
+        Note that :term:`white space` is explicitly allowed in the representation 
         and no canonicalization is performed before encoding.
 
-    4.  Base64url encode the bytes of the UTF-8 representation of the JWT Header. 
-        Let this be the Encoded JWT Header.
+    4.  Base64url encode the bytes of the UTF-8 representation of the :term:`JWT Header`. 
+        Let this be the :term:`Encoded JWT Header`.
 
     5.  Depending upon whether the JWT is to be signed, encrypted, or plaintext, there are three cases:
 
         -   If the JWT is to be signed, 
-            create a JWS using the JWT Header as the JWS Header and the Message as the JWS Payload; 
-            all steps specified in [JWS] for creating a JWS MUST be followed. 
-            Let the JWT Second Part be the Encoded JWS Payload and 
-            let the JWT Third Part be the Encoded JWS Signature.
+            create a JWS using the :term:`JWT Header` as the :term:`JWS Header` 
+            and the :term:`Message` as the :term:`JWS Payload`; 
+
+            all steps specified in [:term:`JWS`] for creating a JWS MUST be followed. 
+
+            Let the :term:`JWT Second Part` be the :term:`Encoded JWS Payload` and 
+            let the :term:`JWT Third Part` be the :term:`Encoded JWS Signature`.
 
         -   If the JWT is to be encrypted, 
-            create a JWE using the JWT Header as the JWE Header and 
-            the Message as the JWE Plaintext; 
-            all steps specified in [JWE] for creating a JWE MUST be followed.
-            Let the JWT Second Part be the Encoded JWE Encrypted Key and 
-            let the JWT Third Part be the Encoded JWS Ciphertext.
+            create a JWE using the :term:`JWT Header` as the :term:`JWE Header` and 
+            the :term:`Message` as the :term:`JWE Plaintext`; 
+
+            all steps specified in [:term:`JWE`] for creating a JWE MUST be followed.
+            Let the :term:`JWT Second Part` be the :term:`Encoded JWE Encrypted Key` and 
+            let the :term:`JWT Third Part` be the :term:`Encoded JWE Ciphertext`.
 
         -   Else, 
-            if the JWT is to be plaintext, 
-            let the JWT Second Part be the base64url encoding of the Message and let the JWT Third Part be the empty string.
+            if the JWT is to be :term:`plaintext`, 
+            let the :term:`JWT Second Part` be the base64url encoding of the :term:`Message` 
+            and let the :term:`JWT Third Part` be the **empty string**.
 
-    6.  Concatenate the Encoded JWT Header, 
-        the JWT Second Part, 
-        and the JWT Third Part in that order, 
-        separating each by period ('.') characters.
+    6.  Concatenate the :term:`Encoded JWT Header`, 
+        the :term:`JWT Second Part`, 
+        and the :term:`JWT Third Part` in that order, 
+        separating each by **period ('.')** characters.
 
     7.  If a nested signing or encryption operation will be performed, 
-        let the Message be this concatenation, and return to Step 3, 
-        using a typ value of either "JWS" or "JWE" respectively in the new JWT Header created in that step.
+        let the :term:`Message` be this concatenation, and return to Step 3, 
+        using a :term:`typ` value of either "JWS" or "JWE" respectively in the new JWT Header created in that step.
 
     8.  Otherwise, let the resulting JWT be this concatenation.
 
 When validating a JWT the following steps MUST be taken. If any of the listed steps fails then the token MUST be rejected for processing.
 
 
-    1.  The JWT MUST contain exactly two period characters.
+    1.  The JWT MUST contain exactly **two period characters**.
 
-    2.  The JWT MUST be split on the two period characters resulting in three strings. The first string is the Encoded JWT Header; the second is the JWT Second Part; the third is the JWT Third Part.
+    2.  The JWT MUST be split on the two period characters resulting in three strings. 
+        The first string is the :term:`Encoded JWT Header`; 
+        the second is the :term:`JWT Second Part`; 
+        the third is the :term:`JWT Third Part`.
 
-    3.  The Encoded JWT Header MUST be successfully base64url decoded following the restriction given in this specification that no padding characters have been used.
+    3.  The :term:`Encoded JWT Header` MUST be successfully **base64url decoded** 
+        following the restriction given in this specification that **no padding characters** have been used.
 
-    4.  The JWT Header MUST be completely valid JSON syntax conforming to RFC 4627 [RFC4627].
+    4.  The :term:`JWT Header` MUST be completely valid JSON syntax conforming to RFC 4627 [:term:`RFC4627`].
 
-    5.  The JWT Header MUST be validated to only include parameters and values whose syntax and semantics are both understood and supported.
+    5.  The :term:`JWT Header` MUST be validated to only include parameters 
+        and values whose syntax and semantics are both understood and supported.
 
-    6.  Determine whether the JWT is signed, encrypted, or plaintext by examining the alg (algorithm) header value and optionally, the enc (encryption method) header value, if present.
+    6.  Determine whether the JWT is signed, encrypted, or plaintext 
+        by examining the :term:`alg` (algorithm) header value and optionally, 
+        the :term:`enc` (encryption method) header value, 
+        if present.
 
     7.  Depending upon whether the JWT signed, encrypted, or plaintext, there are three cases:
 

src/jose/__init__.py

 def get_version():
     version = '%d.%d.%d' % (VERSION[0], VERSION[1], VERSION[2])
     return version
+
+#
+import base64
+import json
+
+def base64url_decode(input):
+    input += '=' * (4 - (len(input) % 4)) 
+    return base64.urlsafe_b64decode(input)
+def base64url_encode(input):
+    return base64.urlsafe_b64encode(input).replace('=', '') 
+
+def to_json(a): return json.dumps(a)
+def from_json(a): return json.loads(a)
+def to_base64(a): return base64url_encode(a)
+def from_base64(a): return base64url_decode(a)
+def encode(a): return to_base64(to_json(a))
+def decode(a): return from_json(from_base64(a))
+
+def args_from_string(token):
+    ret = [token]  + token.split('.')
+    ret[1] = decode(ret[1])    #:deserialize JWT Header 
+    return ret
Add a comment to this file

src/jose/jwe/__init__.py

Empty file added.

src/jose/jws/__init__.py

-from jws import *
+# -*- coding: utf-8 -*-
+# use python-jws
+import jws
+from jose import loads_base64url, dumps_base64url,args_from_string
+
+#
+class SignedToken(object):
+    def __init__(self,token=None,header={},signing_input=None,payload='',signature='',message={}):
+        self.token = token
+        self.header= header
+        self.signing_input = signing_input
+        self.payload = payload
+        self.signature= signature
+        self.message = message
+
+    def verify(self,public_key):
+        if self.signing_input == None:
+            self.signing_input = self.token[:self.token.rindex('.')]
+        if self.signature == '':
+            self.signature = self.token[self.token.rindex('.')+1:]
+        return jws.verify(self.header,{},   
+                self.signature,public_key,
+                    signing_input = self.signing_input )
+
+    def serialize(self,private_key):
+        self.update(private_key)
+        return self.token 
+
+    def deserialize(self):
+        args = args_from_string(self.token)
+        return from_string(*args)
+
+    def update(self,private_key):
+        self.signing_input , self.signature= jws._signing_input(self.header,self.message,key=private_key)
+        self.token = self.signing_input +"." + self.signature
+    
+def from_token(token,dheader,payload,signature):
+    '''
+        :param token:  original string
+        :param header: deserialized JWT Header (dict)
+        :type hader: dict
+    '''
+    _algs = [
+        "HS256",
+        "HS384",
+        "HS512",
+        "RS256",
+        "RS384",
+        "RS512",
+        "ES256",
+        "ES384",
+        "ES512",
+    ]
+
+    if dheader.has_key('alg') == False \
+       and dheader['alg'] not in _algs \
+       or third == None:
+        return None
+
+    signing_input = token.replace("."+signature,'')
+     
+    return SingedToken(token,dheader,signing_input,payload,signature)

src/jose/jws/utils.py

+from jws.utils import *

src/jose/jwt/__init__.py

+# -*- coding: utf-8 -*-
+#
+
+from token import *

src/jose/jwt/tests.py

+# -*- coding: utf-8 -*-
+
+import sys
+if sys.version_info < (2,7):
+    import unittest2 as unittest
+else:
+    import unittest
+
+class TestJWT_helpers(unittest.TestCase):
+    def test_loads_base64url(self):
+        from jose import encode,decode
+        org = {u'a':1,u'b':2,u'c':3,}
+        org_str = encode( org )
+        ret = decode( org_str )
+        ret_str = encode( ret )
+
+        #:TODO: Python json doesn't reproduct objects.... Implement proper test  later
+        self.assertEqual(org_str,ret_str)
+
+    def test_args_from_string(self):
+        from jose import args_from_string
+        token1 = 'e30.e30.'   #: header={} , message = {}
+        args = args_from_string(token1)
+        
+        with self.assertRaises(ValueError):
+            token2 = 'xe30.e30.'   #: header= not seralized JSON , message = {}
+            args = args_from_string(token2)
+        
+        token3 = 'e30.xe30.'   #: header={} , message =  not serialzed JSON
+        args = args_from_string(token3) #: only header is deserialized  
+
+class TestPlainJWT(unittest.TestCase):
+
+    def test_empty_serialize(self):
+        from jose import args_from_string
+        from jose.plain import PlainToken,from_token
+        
+        obj= PlainToken()
+        token = obj.serialize()
+        
+        args = args_from_string(token)
+        print args
+        obj2 = from_token(*args) 
+        self.assertEqual(obj.header,obj2.header)
+        self.assertEqual(obj.message,obj2.message)
+
+    def test_no_trailing_dot(self):
+        from jose import args_from_string
+        from jose.plain import PlainToken,from_token
+
+        token1 = 'e30.e30.'   #: header={} , message = {}
+        token2 = 'e30.e30'   #: header={} , message = {}
+  
+        args = args_from_string(token1)
+        obj = from_token(*args)
+        self.assertNotEqual(obj,None)
+
+        args = args_from_string(token2)
+        obj = from_token(*args)
+        self.assertEqual(obj,None)
+
+    def test_wrong_message(self):
+        token3 = 'e30.xe30.'   #: header={} , message =  not serialzed JSON
+
+        from jose import args_from_string
+        from jose.plain import PlainToken,from_token
+    
+        with self.assertRaises(ValueError):
+            args = args_from_string(token3)
+            obj = from_token(*args)

src/jose/jwt/tokens.py

+# -*- coding: utf-8 -*-
+#
+from jose.jwt import loads_base64url, dumps_base64url,base64url_decode,base64url_encode
+
+def from_string(token_string):
+    ''' 
+        :param  token:   JWT string  
+    '''
+    parts = token_string.split('.')
+    if len(parts)<2:
+        return None
+
+    try:
+        header = load_base64url(parts[1])
+    except :
+        return None
+
+    if header.has_key('alg') == False:
+        return 
+

src/jose/plain/__init__.py

+# -*- coding: utf-8 -*-
+#
+
+from jose import encode, decode,args_from_string
+
+class PlainToken(object):
+    def __init__(self,token=None,header={},message={}):
+        self.token = token
+        self.header= header
+        self.message = message
+
+    def deserialize(self):
+        args = args_from_string(self.token)
+        return from_string(*args)
+
+    def serialize(self):
+        self.update()
+        return self.token
+
+    def verify(self,*args):
+        return True
+
+    def update(self):
+        self.token = ".".join([ encode(self.header),
+                           encode(self.message),
+                         ''])
+    
+def from_token(token,dheader,second,third=None):
+    '''
+        :param token:  original string
+        :param header: deserialized JWT Header (dict)
+        :type hader: dict
+    '''
+    if dheader.has_key('alg') or third == None:
+        return None
+     
+    message = decode(second)
+    return PlainToken(token,dheader,message)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.