django加密签名

Sing.py 中实现了一系列的加密方式:signer 和TimestampSigner
一些加密可能需要首先在settings.py 中添加 SECRET_KEY

具体的使用方法可以使用如下:

from django.core.signing import Signer
signer = Signer()
value = signer.sign('My string')
value
'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'

如果您不希望特定字符串的每次出现具有相同的签名散列,您可以使用可选的salt参数到Signer类,解密的时候不需要传入salt 参数

signer = Signer()
signer.sign('My string')

'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'

signer = Signer(salt='extra')
signer.sign('My string')

'My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw'

signer = Signer(salt='e')
signer.sign('My string')

'My string:9v2dnmMn6i6XkGqoz1sYnKk-GjE'

signer.unsign('My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw')

'My string'

Timestamp Signer是Singer的一个子类,它将一个带符号的时间戳附加到该值。 这允许您确认在指定的时间段内创建了一个签名的值:

from datetime import timedelta
from django.core.signing import TimestampSigner
signer = TimestampSigner()
value = signer.sign('hello')
value

'hello:1NMg5H:oPVuCqlJWmChm1rA2lyTUtelC-c'

signer.unsign(value)

'hello'

signer.unsign(value, max_age=10)

...
SignatureExpired: Signature age 15.5289158821 > 10 seconds

signer.unsign(value, max_age=20)

'hello'

signer.unsign(value, max_age=timedelta(seconds=20))

'hello'

保护数据,要传递一些敏感数据,可以使用加密传动

from django.core import signing
value = signing.dumps({"foo": "bar"})
value

'eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI'

signing.loads(value)

{'foo': 'bar'}

多个数据

from django.core import signing
value = signing.dumps(('a','b','c'))
signing.loads(value) ['a', 'b', 'c']

用户名的密码加密解密方式:

 加密

用户名的加密方式在Django 源码里使用了make_password() 这个方法实现
函数的原型是:
def make_password(password, salt=None, hasher='default'):

"""
Turn a plain-text password into a hash for database storage

Same as encode() but generates a new random salt.
If password is None then a concatenation of
UNUSABLE_PASSWORD_PREFIX and a random string will be returned
which disallows logins. Additional random string reduces chances
of gaining access to staff or superuser accounts.
See ticket #20079 for more info.
"""
if password is None:
    return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)
hasher = get_hasher(hasher)

if not salt:
    salt = hasher.salt()#get_random_string
return hasher.encode(password, salt)

#这里面设计到sha256, randow.getstate(),random.speed()

random.getstate()

           (3, (2147483648, 4018322764, 577648385, 1526147929, 1680474043, 3919679311, 2889319108, 4191545603,                            2720450620, 3365467495, 3734949539, 673801099,None)

hashlib.sha256(('%s' % time.time).encode('utf-8')).digest()

       b"1=_\xaa\x90\xa4\xe9\x86au\xb0'\xfaJ\x83\xb9%\x11E\x9f\xed\x0c\x15}\x9d&\xfb\xc72\xa6Z\xcf"

def get_random_string(length=12,

                  allowed_chars='abcdefghijklmnopqrstuvwxyz'
                                'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
"""
Returns a securely generated random string.

The default length of 12 with the a-z, A-Z, 0-9 character set returns
a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
"""
if not using_sysrandom:
    # This is ugly, and a hack, but it makes things better than
    # the alternative of predictability. This re-seeds the PRNG
    # using a value that is hard for an attacker to predict, every
    # time a random string is required. This may change the
    # properties of the chosen random sequence slightly, but this
    # is better than absolute predictability.
    random.seed(
        hashlib.sha256(
            ("%s%s%s" % (
                random.getstate(),
                time.time(),
                settings.SECRET_KEY)).encode('utf-8')
        ).digest())
return ''.join(random.choice(allowed_chars) for i in range(length))

最后结合这两个函数生成一个密文hasher.encode(password, salt)

slat 参数

默认提供了一个随机的salt 参数,因此对于同一个密码每次都会有不同的密文出现例如:

make_password('test')
'pbkdf2_sha256$36000$isQNwbk2iwg1$nVHLwSeHziSu/N2gP8QJNgAJjBb879hOdDMim++t0SU='
make_password('test')

'pbkdf2_sha256$36000$QxlN97KubUTA$U2GGmXhL3cBgVpYfwXGgW659EYV8W/MJBFzH/v6IN3A='

make_password('test')

'pbkdf2_sha256$36000$80Z9aOgA7IX9$+3lWsQvl1qENNfrxt5ThoYbStk+xh+wXbYZznqSlvPA='

解密

解密同样提供了一个方式check_password:

check_password('test','pbkdf2_sha256$36000$80Z9aOgA7IX9$+3lWsQvl1qENNfrxt5ThoYbStk+xh+wXbYZznqSlvPA=')

True

函数原型

def check_password(password, encoded, setter=None, preferred='default'):

"""
Returns a boolean of whether the raw password matches the three
part encoded digest.

If setter is specified, it'll be called when you need to
regenerate the password.
"""
if password is None or not is_password_usable(encoded):
    return False

preferred = get_hasher(preferred)
hasher = identify_hasher(encoded)

hasher_changed = hasher.algorithm != preferred.algorithm
must_update = hasher_changed or preferred.must_update(encoded)
is_correct = hasher.verify(password, encoded)

# If the hasher didn't change (we don't protect against enumeration if it
# does) and the password should get updated, try to close the timing gap
# between the work factor of the current encoded password and the default
# work factor.
if not is_correct and not hasher_changed and must_update:
    hasher.harden_runtime(password, encoded)

if setter and is_correct and must_update:
    setter(password)
return is_correct
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值