Comment décoder l'url base64 en python?

pour les applications FBML Facebook envoie un paramètre signed_request expliqué ici:

http://developers.facebook.com/docs/authentication/canvas

Ils ont donné la version de php de décodage de cette demande signée:

http://pastie.org/1054154

Comment faire la même chose en python?

j'ai essayé le module base64 mais je reçois une erreur de rembourrage incorrecte:

>>> base64.urlsafe_b64decode("eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk3NDYwMDAsIm9hdXRoX3Rva2VuIjoiMjk1NjY2Njk1MDY0fDIuRXpwem5IRVhZWkJVZmhGQ2l4ZzYzUV9fLjM2MDAuMTI3OTc0NjAwMC0xMDAwMDA0ODMyNzI5MjN8LXJ6U1pnRVBJTktaYnJnX1VNUUNhRzlNdEY4LiIsInVzZXJfaWQiOiIxMDAwMDA0ODMyNzI5MjMifQ")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/base64.py", line 112, in urlsafe_b64decode
    return b64decode(s, '-_')
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/base64.py", line 76, in b64decode
    raise TypeError(msg)
TypeError: Incorrect padding
18
demandé sur Pratiksha 2010-07-21 23:18:34

6 réponses

apparemment, vous avez manqué les deux derniers caractères en copiant la chaîne originale encodée en base64. Suffixez la chaîne de caractères avec deux signes is-equal (=) et elle sera décodée correctement.

19
répondu Geert 2010-07-21 20:07:29

j'ai partagé un extrait de code pour l'analyse du paramètre signed_request dans une application canvas facebook basée sur python à http://sunilarora.org/parsing-signedrequest-parameter-in-python-bas:

import base64
import hashlib
import hmac
import simplejson as json

def base64_url_decode(inp):
    padding_factor = (4 - len(inp) % 4) % 4
    inp += "="*padding_factor 
    return base64.b64decode(unicode(inp).translate(dict(zip(map(ord, u'-_'), u'+/'))))

def parse_signed_request(signed_request, secret):

    l = signed_request.split('.', 2)
    encoded_sig = l[0]
    payload = l[1]

    sig = base64_url_decode(encoded_sig)
    data = json.loads(base64_url_decode(payload))

    if data.get('algorithm').upper() != 'HMAC-SHA256':
        log.error('Unknown algorithm')
        return None
    else:
        expected_sig = hmac.new(secret, msg=payload, digestmod=hashlib.sha256).digest()

    if sig != expected_sig:
        return None
    else:
        log.debug('valid signed request received..')
return data
24
répondu sunil 2017-09-15 08:49:29

s = 'iEPX-SQWIR3p67lj_0zigSWTKHg'
base64.urlsafe_b64decode(s + '=' * (4 - len(s) % 4))

comme il est écrit ici

21
répondu dae.eklen 2012-03-31 13:16:19

Alternative à @dae.la solution d'eklen, vous pouvez ajouter ===:

s = 'iEPX-SQWIR3p67lj_0zigSWTKHg'
base64.urlsafe_b64decode(s + '===')

cela fonctionne parce que Python se plaint seulement de l'absence de rembourrage, mais pas de rembourrage supplémentaire.

4
répondu png 2015-04-02 18:26:55
import base64
import simplejson as json

def parse_signed_request( signed_request ):
    encoded_sig, payload = signed_request.split('.',2)
    data = json.loads(base64.b64decode( payload.replace('-_', '+/') ))
    return data
1
répondu FazalSap 2012-01-24 12:19:35

surprenant, mais la réponse actuellement acceptée n'est pas exactement correcte. Comme d'autres réponses l'indiquent, c'est quelque chose appelé encodage base64url, et cela fait partie de RFC7515.

En Gros, ils ont remplacé les caractères " + " et " / " par " - " et " _ "respectivement; et en plus, ils ont supprimé les caractères traînants"=", parce que vous pouvez toujours dire combien de caractères vous manquez, simplement en regardant la longueur de chaîne encodée.

voici un exemple de RFC7515 in C#:

 static string base64urlencode(byte [] arg)
 {
   string s = Convert.ToBase64String(arg); // Regular base64 encoder
   s = s.Split('=')[0]; // Remove any trailing '='s
   s = s.Replace('+', '-'); // 62nd char of encoding
   s = s.Replace('/', '_'); // 63rd char of encoding
   return s;
 }

 static byte [] base64urldecode(string arg)
 {
   string s = arg;
   s = s.Replace('-', '+'); // 62nd char of encoding
   s = s.Replace('_', '/'); // 63rd char of encoding
   switch (s.Length % 4) // Pad with trailing '='s
   {
     case 0: break; // No pad chars in this case
     case 2: s += "=="; break; // Two pad chars
     case 3: s += "="; break; // One pad char
     default: throw new System.Exception(
       "Illegal base64url string!");
   }
   return Convert.FromBase64String(s); // Standard base64 decoder
 }
1
répondu Vladimir Menshakov 2018-03-25 19:34:07