django 1.8 官方文档翻译:8-5 加密签名

王荣
• 阅读 2930

加密签名

web应用安全的黄金法则是,永远不要相信来自不可信来源的数据。有时通过不可信的媒介来传递数据会非常方便。密码签名后的值可以通过不受信任的途径传递,这样是安全的,因为任何篡改都会检测的到。

Django提供了用于签名的底层API,以及用于设置和读取被签名cookie的上层API,它们是web应用中最常使用的签名工具之一。

你可能会发现,签名对于以下事情非常有用:

  • 生成用于“重置我的账户”的URL,并发送给丢失密码的用户。

  • 确保储存在隐藏表单字段的数据不被篡改,

  • 生成一次性的秘密URL,用于暂时性允许访问受保护的资源,例如用户付费的下载文件。

保护 SECRET_KEY

当你使用 startproject创建新的Django项目时,自动生成的 settings.py文件会得到一个随机的SECRET_KEY值。这个值是保护签名数据的密钥 -- 它至关重要,你必须妥善保管,否则攻击者会使用它来生成自己的签名值。

使用底层 API

Django的签名方法存放于django.core.signing模块。首先创建一个 Signer 的实例来对一个值签名:

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

这个签名会附加到字符串末尾,跟在冒号后面。你可以使用unsign方法来获取原始的值:

>>> original = signer.unsign(value)
>>> original
'My string'

如果签名或者值以任何方式改变,会抛出django.core.signing.BadSignature 异常:

>>> from django.core import signing
>>> value += 'm'
>>> try:
...    original = signer.unsign(value)
... except signing.BadSignature:
...    print("Tampering detected!")

通常,Signer类使用SECRET_KEY设置来生成签名。你可以通过向Signer构造器传递一个不同的密钥来使用它:

>>> signer = Signer('my-other-secret')
>>> value = signer.sign('My string')
>>> value
'My string:EkfQJafvGyiofrdGnuthdxImIJw'

class Signer(key=None, sep=':', salt=None)[source]

返回一个signer,它使用key 来生成签名,并且使用sep来分割值。sep 不能是 [URL安全的base64字母表(http://tools.ietf.org/html/rfc4648#section-5)]中的字符。字母表含有数字、字母、连字符和下划线。

使用salt参数

如果你不希望对每个特定的字符串都生成一个相同的签名哈希值,你可以在Signer类中使用可选的salt 参数。使用salt参数会同时用它和SECRET_KEY初始化签名哈希函数:

>>> signer = Signer()
>>> signer.sign('My string')
'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'
>>> signer = Signer(salt='extra')
>>> signer.sign('My string')
'My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw'
>>> signer.unsign('My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw')
'My string'

以这种方法使用salt会把不同的签名放在不同的命名空间中。来自于单一命名空间(一个特定的salt值)的签名不能用于在不同的命名空间中验证相同的纯文本字符串。不同的命名空间使用不同的salt设置。这是为了防止攻击者使用在一个地方的代码中生成的签名后的字符串,作为使用不同salt来生成(和验证)签名的另一处代码的输入。

不像你的SECRET_KEY,你的salt参数可以不用保密。

验证带有时间戳的值

TimestampSignerSigner的子类,它向值附加一个签名后的时间戳。这可以让你确认一个签名后的值是否在特定时间段之内被创建:

>>> 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'

class TimestampSigner(key=None, sep=':', salt=None)[source]

sign(value)[source]

签名value,并且附加当前的时间戳。

unsign(value, max_age=None)[source]

检查value是否在少于max_age 秒之前被签名,如果不是则抛出SignatureExpired异常。max_age 参数接受一个整数或者datetime.timedelta对象。

Changed in Django 1.8:

在此之前, max_age参数只接受整数。

保护复杂的数据结构

如果你希望保护一个列表、元组或字典,你可以使用签名模块的dumpsloads 函数来实现。它们模仿了Python的pickle模块,但是在背后使用了JSON序列化。JSON可以确保即使你的SECRET_KEY被盗取,攻击者并不能利用pickle的格式来执行任意的命令:

>>> from django.core import signing
>>> value = signing.dumps({"foo": "bar"})
>>> value
'eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI'
>>> signing.loads(value)
{'foo': 'bar'}

由于JSON的本质(列表和元组之间没有原生的区别),如果你传进来一个元组,你会从signing.loads(object)得到一个列表:

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

dumps(obj, key=None, salt='django.core.signing', compress=False)[source]

返回URL安全,sha1签名的base64压缩的JSON字符串。序列化的对象使用TimestampSigner来签名。

loads(string, key=None, salt='django.core.signing', max_age=None)[source]

dumps()的反转,如果签名失败则抛出BadSignature异常。如果提供了max_age则会检查它(以秒为单位)。

译者:Django 文档协作翻译小组,原文:Cryptographic signing

本文以 CC BY-NC-SA 3.0 协议发布,转载请保留作者署名和文章出处。

Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。交流群:467338606。

点赞
收藏
评论区
推荐文章
浅谈加密算法 aes
一、目标搞了这么多期签名和加密解密,今天我们聊聊高大上的东西:加密算法。加密算法我们整体可以分为:不可逆加密算法和可逆加密算法。不可逆加密算法常见的不可逆加密算法有MD5,HMAC,SHA1、SHA224、SHA256、SHA384,和SHA512。他们的特点是,不能从加密后的结果解密出原文,主要用于校检数据的一致性,防止篡改数据,我们之前分析的大部分s
开放API接口签名验证,让你的接口从此不再裸奔
接口安全问题请求身份是否合法?请求参数是否被篡改?请求是否唯一?AccessKey&SecretKey(开放平台)请求身份为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。防止篡改参数签名1.按照请求参数名的字母升序排列非空请求参数(包含AccessK
木马病毒你需要知道的15个技术点。
木马病毒方式1:模块通过三方签名过杀毒检测,注册表进行开机启动,通过url进行数据传递,释放不同exe或者文件进行木马功能,感染的dll数据会通过加密,会通过注入explorer.exe,services.exe,spoolsv.exe进行功能实现。木马病毒方式2:通过向系统进程services.exe,explorer.exe,svchost.exe注
Stella981 Stella981
3年前
Linux CA
CA(CertificateAuthority)证书颁发机构主要负责证书的颁发、管理以及归档和吊销。证书内包含了拥有证书者的姓名、地址、电子邮件帐号、公钥、证书有效期、发放证书的CA、CA的数字签名等信息。证书主要有三大功能:加密、签名、身份验证。1.什么是CA认证?CA认证,即CA认证机构,为电子签名相关各方提供真实性、可靠性验证
Stella981 Stella981
3年前
Spring Boot 整合 JWT
1、JWT是什么?JWT是一个开放标准,它定义了一种用于简洁,自包含的用于通信双方之间以JSON对象的形式安全传递信息的方法。JWT可以使用HMAC算法或者是RSA的公钥密钥对进行签名。简单来说,就是通过一定规范来生成token,然后可以通过解密算法逆向解密token,这样就可以获取用户信息。优点:1)生产的t
Wesley13 Wesley13
3年前
JAVA_RSA_的加解密
RSA为非对称加密算法。数字签名的过程:1、对明文数据进行HASH加密,不可逆;2、对加密后的数据再用RSA的私钥进行二次加密。数字签名的验证过程:1、对明文数据进行HASH加密,不可逆;2、用RSA的公钥对数字签名后的数据进行解密;3、把1的结果和2的结果进行比较是否相等。RSA加密的过程和解密的过程都需要三步:加/解密、分组、填充。这三部分每
Wesley13 Wesley13
3年前
JAVA加解密算法设计与应用
业务场景APP移动端、WEB、桌面端、第三方平台密码等敏感数据加密设计如app端登录密码加密设计对于登录密码不需要进行解密只需要加密算法结合规则进行比较就能得到密码正确与否方法一(签名保证安全)1.密码等敏感信息取Md5值对所有值(加上timestamp)
Wesley13 Wesley13
3年前
PHP签名
<?phpclassSign{/获取数据签名@paramarray$param签名数组@paramstring$code安全校验码@param
Wesley13 Wesley13
3年前
VC++网络安全编程范例(2)
数字证书采用公钥体制,即利用一对互相匹配的密钥进行加密、解密。每个用户自己设定一把特定的仅为本人所知的私有密钥(私钥),用它进行解密和签名;同时设定一把公共密钥(公钥)并由本人公开,为一组用户所共享,用于加密和验证签名。当发送一份保密文件时,发送方使用接收方的公钥对数据加密,而接收方则使用自己的私钥解密,这样信息就可以安全无误地到达目的地了。通过数字的手段
Wesley13 Wesley13
3年前
Exchange Server 的OWA 邮件签名大小限制
随着电子邮件的普及应用,五花八门的邮件签名也随着每个人的创意诞生了。作为ExchangeServer的客户端访问方式之一,OWA也同样提供了邮件签名的设置选项。但是,有时用户会发现,当他想在OWA中为自己的邮箱设定一个COOL的邮件签名时,有可能会得到“未保存您的更改,因为电子邮件签名过大。请使用较小的格式。”这样的错误。为什么?原来OWA邮件签名大小也
网页防篡改技术:保护网站安全与完整性的关键
页防篡改需要应用多种技术手段,包括使用数字签名、监测软件、IP封堵、数据加密等方式,以便有效地检测和预防网页被恶意篡改的行为。