def test_naive_token_hijacking_fails(self): # The revocation key may be identical for two users: # - if SESAME_INVALIDATE_ON_PASSWORD_CHANGE is False or if they don't # have a password; # - if SESAME_ONE_TIME is False or if they have the same last_login. # In that case, could one user could impersonate the other? user1 = self.user user2 = self.create_user("jane") token1 = create_token(user1) token2 = create_token(user2) # Check that the test scenario produces identical revocation keys. # This test depends on the implementation of django.core.signing; # however, the format of tokens must be stable to keep them valid. data1, sig1 = token1.split(":", 1) data2, sig2 = token2.split(":", 1) data1 = signing.b64_decode(data1.encode()) data2 = signing.b64_decode(data2.encode()) pk1 = packers.packer.pack_pk(user1.pk) pk2 = packers.packer.pack_pk(user2.pk) self.assertEqual(data1[: len(pk1)], pk1) self.assertEqual(data2[: len(pk2)], pk2) key1 = data1[len(pk1) :] key2 = data2[len(pk2) :] self.assertEqual(key1, key2) # Check that changing just the primary key doesn't allow hijacking the # other user's account. data = pk2 + key1 data = signing.b64_encode(data).decode() token = data + sig1 user = parse_token(token, self.get_user) self.assertIsNone(user) self.assertLogsContain("Bad token")
def verify_and_load(candidate, salt): payload = smart_str(signing.Signer(None, salt=salt).unsign(candidate)) if payload[0] == '.': data = zlib.decompress(signing.b64_decode(payload[1:])) else: data = signing.b64_decode(payload) return signing.JSONSerializer().loads(data)
def token_check(token): '''token验证''' try: src = signing.b64_decode(token.encode()).decode() dat = signing.b64_decode(src.encode()).decode() stk = Token.objects.get(id=1).token if dat != stk: return 'False' else: return 'True' except : return 'False'
def loads( s, key=None, salt: str = "django.core.signing", serializer=JSONSerializer, max_age=None, ): """ Reverse of dumps(), raise BadSignature if signature fails. The serializer is expected to accept a bytestring. """ # TimestampSigner.unsign() returns str but base64 and zlib compression # operate on bytes. base64d = force_bytes( TimestampSigner(key, salt=salt).unsign(s, max_age=max_age)) decompress = False if base64d[:1] == b".": # It's compressed; uncompress it first base64d = base64d[1:] decompress = True data = b64_decode(base64d) if decompress: data = zlib.decompress(data) return serializer().loads(data)
def post(self, request, *args, **kwargs): url_token = kwargs["token"] try: data = signing.TimestampSigner(salt="radiologo").unsign(url_token) decoded = signing.b64_decode(data.encode()) pk = (struct.unpack(str("!i"), decoded[:4])[0], decoded[4:])[0] except BadSignature: raise BadInviteTokenException user = get_object_or_404(get_user_model(), pk=pk) invite = Invite.objects.get(invited_user=user) self.check_different_token(url_token, invite.sent_token) self.check_expired(invite) self.check_accepted(invite) password = request.data["password"] validate_password(password, user=user, password_validators=get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)) user.set_password(password) invite.accepted = True user.is_registered = True user.save() invite.save() return Response(status=status.HTTP_200_OK)
def find(request, token): try: signer = TimestampSigner(key=request.session.session_key, sep=':') id = b64_decode(signer.unsign(token, max_age=86400).encode('utf-8')) return AsyncResult(id) except: return None
def find(request, token): try: signer = TimestampSigner(key=request.session.session_key, sep=':') id = b64_decode(signer.unsign(token, max_age=Task.TIMEOUT).encode('utf-8')) return Task.status(id) except: return None
def get_express_session(req, cookie_name='express_sess'): """ get the Express.js session dict. default session cookie name of express:sess does now work with django. """ key = settings.SECRET_KEY cookie_value = req.COOKIES.get(cookie_name) cookie_sig = req.COOKIES.get(cookie_name + '.sig') if not cookie_value or not cookie_sig: return {} cookie = cookie_name + '=' + cookie_value hmac = Hmac.new(key, cookie, hashlib.sha1) digest = signing.b64_encode(hmac.digest()) valid_sig = crypto.constant_time_compare(digest, cookie_sig) if not valid_sig: return {} try: json_data = signing.b64_decode(cookie_value) session = json.loads(json_data) except: return {} return session
def verify_email(self, code): if code: signer = TimestampSigner() try: code = code.encode('utf-8') max_age = datetime.timedelta( days=settings.VERIFICATION_CODE_EXPIRED).total_seconds() code = force_bytes(code) code = b64_decode(code) code = code.decode() email = signer.unsign(code, max_age=max_age) user = StdUser.objects.get(**{ StdUser.USERNAME_FIELD: email, 'is_active': False }) user.is_active = True user.code = "None code" user.save() return True, ('Your account has been activated.') except (BadSignature, StdUser.DoesNotExist, TypeError, UnicodeDecodeError): raise ValueError('Error') return False, ( 'Activation link is incorrect, please resend request') else: raise ValueError('No code')
def unsign(self, token): """Extract the data from a signed `token`.""" if self.max_age is None: data = self.signer.unsign(token) else: data = self.signer.unsign(token, max_age=self.max_age) return signing.b64_decode(data.encode())
def parse_token(token): """ Pull apart a signed token and try to obtain a user. Returns the user object if it is a Valid, Existing, Signature-Verified token. Otherwise returns None. """ try: username = json.loads( b64_decode(token.split(':')[0].encode()).decode()) # Quite a few things could go wrong here; catch all at once for now except: return UserModel = get_user_model() try: user = UserModel.objects.get(username=username) except UserModel.DoesNotExist: return # Double check the signature is valid given the salt based on the # user's password hash. salt = TOKEN_SALT_PREFIX + user.password try: username = loads(token, salt=salt) except SignatureExpired: return except BadSignature: return # Should be good if we got this far, but... if user.username == username: return user else: return
def decrypt(src): """解密""" src = signing.b64_decode(src.encode()).decode() raw = signing.loads(src, key=KEY, salt=SALT) # print(raw) # print(type(raw)) return raw
def token_decode(token): """ Extracts the content_type_id and object_id values from the packed string. """ data = b64_decode(smart_str(token)) # Get the sizes of our values offset = 0 format = '!B' (size,) = struct.unpack_from(format, data, offset) type_len = (size & 0b11110000) >> 4 obj_len = (size & 0b00001111) # Get content_type_id and object_id offset += struct.calcsize(format) format = '!%ds%ds' % (type_len, obj_len) content_type_id, object_id = struct.unpack_from(format, data, offset) # Add pad bytes and unpack ``unsigned long long`` values content_type_id, object_id = struct.unpack('!QQ', '%s%s' % ( content_type_id.rjust(8, '\0'), object_id.rjust(8, '\0') )) return content_type_id, object_id
def find(request, token): try: signer = TimestampSigner(key=request.session.session_key, sep=':') id = b64_decode( signer.unsign(token, max_age=Task.TIMEOUT).encode('utf-8')) return Task.status(id) except: return None
def test_set_messages_success(self): author = {'name': 'John Doe', 'slug': 'success-msg'} add_url = reverse('add_success_msg') req = self.client.post(add_url, author) # Uncompressed message is stored in the cookie. value = b64_decode( req.cookies['messages'].value.split(":")[0].encode(), ).decode() self.assertIn(ContactFormViewWithMsg.success_message % author, value)
def test_legacy_encode_decode(self): # RemovedInDjango41Warning: pre-Django 3.2 encoded messages will be # invalid. storage = self.storage_class(self.get_request()) messages = [ 'this', Message(0, 'Successfully signed in as [email protected]') ] # Encode/decode a message using the pre-Django 3.2 format. encoder = MessageEncoder() value = encoder.encode(messages) with self.assertRaises(binascii.Error): b64_decode(value.encode()) signer = get_cookie_signer(salt=storage.key_salt) encoded_messages = signer.sign(value) decoded_messages = storage._decode(encoded_messages) self.assertEqual(messages, decoded_messages)
def find_temporary_file(token): signer = TimestampSigner(sep=':') filename, attachment_filename, mimetype = b64_decode(signer.unsign( token, max_age=TEMPORARY_FILE_TTL).encode('utf-8')).split(',') return ( secure_join(settings.MEDIA_ROOT, 'temporary', filename), attachment_filename, mimetype, )
def test_set_messages_success(self): author = {"name": "John Doe", "slug": "success-msg"} add_url = reverse("add_success_msg") req = self.client.post(add_url, author) # Uncompressed message is stored in the cookie. value = b64_decode( req.cookies["messages"].value.split(":")[0].encode(), ).decode() self.assertIn(ContactFormViewWithMsg.success_message % author, value)
def test_make_sure_token_is_decodable(self): token = self.client.generate_api_token(self.user) # A token is really a string containing the json dict, # a timestamp and a signature, separated by ':'. The base64 encoding # lacks padding, which is why we need to use signing.b64_decode() which # handles that for us. data = json.loads(signing.b64_decode(token.split(':')[0])) assert data['user_id'] == self.user.pk assert data['auth_hash'] == self.user.get_session_auth_hash()
def unsign(token): """ Extract the data from a signed ``token``. """ if settings.MAX_AGE is None: data = signer.unsign(token) else: data = signer.unsign(token, max_age=settings.MAX_AGE) return signing.b64_decode(data.encode())
def decrypt(src): """解密""" src = signing.b64_decode(src.encode()).decode() try: raw = signing.loads(src, key=KEY, salt=SALT) except BadSignature: print("解密失败") else: print(raw) return raw
def unsign(self, token): """ Extract the data from a signed `token`. """ if self.max_age is None: data = self.signer.unsign(token) else: data = self.signer.unsign(token, max_age=self.max_age) return signing.b64_decode(data.encode())
def test_naive_token_hijacking_fails(self): # Tokens contain the PK of the user, the hash of the revocation key, # and a signature. The revocation key may be identical for two users: # - if SESAME_INVALIDATE_ON_PASSWORD_CHANGE is False or if they don't # have a password; # - if SESAME_ONE_TIME is False or if they have the same last_login. User = get_user_model() last_login = timezone.now() - datetime.timedelta(3600) user_1 = User.objects.create(username="******", last_login=last_login,) user_2 = User.objects.create(username="******", last_login=last_login,) token1 = self.backend.create_token(user_1) token2 = self.backend.create_token(user_2) self.backend.unsign(token1) self.backend.unsign(token2) # Check that the test scenario produces identical revocation keys. # This test depends on the implementation of django.core.signing; # however, the format of tokens must be stable to keep them valid. data1, sig1 = token1.split(self.backend.signer.sep, 1) data2, sig2 = token2.split(self.backend.signer.sep, 1) bin_data1 = signing.b64_decode(data1.encode()) bin_data2 = signing.b64_decode(data2.encode()) pk1 = self.backend.packer.pack_pk(user_1.pk) pk2 = self.backend.packer.pack_pk(user_2.pk) self.assertEqual(bin_data1[: len(pk1)], pk1) self.assertEqual(bin_data2[: len(pk2)], pk2) key1 = bin_data1[len(pk1) :] key2 = bin_data2[len(pk2) :] self.assertEqual(key1, key2) # Check that changing just the PK doesn't allow hijacking the other # user's account -- because the PK is included in the signature. bin_data = pk2 + key1 data = signing.b64_encode(bin_data).decode() token = data + sig1 user = self.backend.parse_token(token) self.assertEqual(user, None) self.assertIn("Bad token", self.get_log())
def check_for_base64_upgrade(queries): if not queries: return # Strip of the timing bit if there is one queries = [q.split(":")[0] for q in queries] # If every query is base64-encoded JSON, return a new querystring if not all(is_valid_base64_json(query) for query in queries): return # Need to decode these and upgrade them to ?sql= links sqls = [] for query in queries: sqls.append(sign_sql(json.loads(signing.b64_decode(query.encode())))) return "?" + urllib.parse.urlencode({"sql": sqls}, True)
def loads(s, key=None, salt='django.core.signing', serializer=JSONSerializer, max_age=None): """ Reverse of dumps(), raises BadSignature if signature fails. The serializer is expected to accept a bytestring. """ # TimestampSigner.unsign always returns unicode but base64 and zlib # compression operate on bytes. base64d = force_bytes(TimestampSigner(key, salt=salt).unsign(s, max_age=max_age)) decompress = False if base64d[:1] == b'.': # It's compressed; uncompress it first base64d = base64d[1:] decompress = True data = b64_decode(base64d) if decompress: data = zlib.decompress(data) return serializer().loads(data)
def verify_password(self, code, password): if code: signer = TimestampSigner() try: code = code.encode('utf-8') max_age = datetime.timedelta(days=settings.VERIFICATION_CODE_EXPIRED).total_seconds() code = force_bytes(code) code = b64_decode(code) code = code.decode() email = signer.unsign(code, max_age=max_age) user = StdUser.objects.get(**{StdUser.USERNAME_FIELD: email}) user.set_password(password) user.code = 'None code' user.save() return True except (BadSignature, AttributeError, StdUser.DoesNotExist, TypeError, UnicodeDecodeError): raise ValueError('Error') return False, ('Activation link is incorrect, please resend request') else: raise ValueError('No code')
def decrypt(obj): """解密""" src = signing.b64_decode(obj.encode()).decode() raw = signing.loads(src, key=KEY, salt=SALT) print('类型:', type(raw)) return raw
def jie_mi(self, cls): #解密 s = signing.b64_decode(cls.encode()).decode() jie_mi = signing.loads(s, key=self.KEY, salt=self.SALT) return jie_mi
def loads(self, s): base64d = encoding.force_bytes( signing.Signer(salt=self.salt).unsign(s)) data = signing.b64_decode(base64d) return json.loads(data.decode('utf-8'))
def is_valid_base64_json(s): try: json.loads(signing.b64_decode(s.encode())) return True except (json.JSONDecodeError, binascii.Error, UnicodeDecodeError): return False
def _decode(self, token): key, value = force_bytes(token, encoding='latin-1').split(b'$', 1) return force_text(xor(b64_decode(value), key), encoding='latin-1')
def decrypt(src): """解密""" src = signing.b64_decode(src.encode()).decode() raw = signing.loads(src, key='liming', salt='www.gongliming.com') return raw
def unsign(self, token): """Extract the data from a signed `token`.""" return signing.b64_decode(self.signer.unsign(token).encode())
def decrypt(dvalue): src = signing.b64_decode(dvalue.encode()).decode() raw = signing.loads(src, key=KEY, salt=SALT) return raw
def decrypt(self, src): src = signing.b64_decode(src.encode()).decode() raw = signing.loads(src, key=self.KEY, salt=self.SALT) return raw
def _unsign(str): # Will raise `signing.BadSignature` for bad strings. data = force_bytes(_signer.unsign(str)) json = signing.b64_decode(data) return signing.JSONSerializer().loads(json)