Cryptographic signing 记忆线索

来源:互联网 发布:来个淘宝买水果靠谱的 编辑:程序博客网 时间:2024/06/05 13:34

Cryptographic signing

The golden rule of Web application security is to never trust data from untrusted sources. Sometimes it can be useful to pass data through an untrusted medium. Cryptographically signed values can be passed through an untrusted channel safe in the knowledge that any tampering will be detected.

★ web 安全的黄金法则是永远不要信任不可靠的资源,在使用不可靠的中间件时尤其是如此。 隐蔽的签名值可以以安全的方式检测出是否被篡改。 

Django provides both a low-level API for signing values and a high-level API for setting and reading signed cookies, one of the most common uses of signing in Web applications.

★ Django 为签名值提供了一个低级API,为读写签名cookies提供了高级API 

You may also find signing useful for the following:

  • Generating “recover my account” URLs for sending to users who have lost their password.   ★ 帮助用户取回密码,生成 URLs
  • Ensuring data stored in hidden form fields has not been tampered with.   ★ 确保在 hidden form fields 里的值没有被篡改    
  • Generating one-time secret URLs for allowing temporary access to a protected resource, for example a downloadable file that a user has paid for.    ★ 为访问被保护资源生成一次性 URLs 

Protecting the SECRET_KEY

When you create a new Django project using startproject, the settings.py file is generated automatically and gets a random SECRET_KEY value. This value is the key to securing signed data – it is vital you keep this secure, or attackers could use it to generate their own signed values.

★ 当用 startproject 创建一个新的 django 工程时, settings.py 文件自动生成,并得到一个 随机的 SECRET_KEY 值。这个值可以加固数据 -- 必须保证其安全性,否则攻击者可以使用它生成自己的签名 

Using the low-level API

Django’s signing methods live in the django.core.signing module. To sign a value, first instantiate a Signer instance:

★ Django 签名方法在 django.core.signing 模块里。 

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

The signature is appended to the end of the string, following the colon. You can retrieve the original value using the unsign method:

★ 签名在字符串的最后面,在冒号之后。可以用 unsign 方法检索原始值 

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

If the signature or value have been altered in any way, a django.core.signing.BadSignature exception will be raised:

★ 如果签名值被篡改,会引发异常 

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

By default, the Signer class uses the SECRET_KEY setting to generate signatures. You can use a different secret by passing it to the Signer constructor:

★ 默认用配置文件里的 SECRET_KEY 值,可以在 Signer 构造函数里使用不同的秘钥  

>>> signer = Signer('my-other-secret')>>> value = signer.sign('My string')>>> value'My string:EkfQJafvGyiofrdGnuthdxImIJw'
class Signer(key=Nonesep=':'salt=None)

Returns a signer which uses key to generate signatures and sep to separate values. sep cannot be in the URL safe base64 alphabet. This alphabet contains alphanumeric characters, hyphens, and underscores.

★ 用秘钥生成签名的类 

Using the salt argument

If you do not wish for every occurrence of a particular string to have the same signature hash, you can use the optional salt argument to the Signer class. Using a salt will seed the signing hash function with both the salt and your SECRET_KEY:   ★ 如果不想生成的每个签名都用同样的秘钥,可以用可选参数 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.unsign('My string:Ee7vGi-ING6n02gkcJ-QLHg6vFw')u'My string'

Using salt in this way puts the different signatures into different namespaces. A signature that comes from one namespace (a particular salt value) cannot be used to validate the same plaintext string in a different namespace that is using a different salt setting. The result is to prevent an attacker from using a signed string generated in one place in the code as input to another piece of code that is generating (and verifying) signatures using a different salt.

Unlike your SECRET_KEY, your salt argument does not need to stay secret.

Verifying timestamped values

TimestampSigner is a subclass of Signer that appends a signed timestamp to the value. This allows you to confirm that a signed value was created within a specified period of time:

★ TimestampSigner 是一个 Singer 的子类,它能够确保签名在制定的日期之内 

>>> from django.core.signing import TimestampSigner>>> signer = TimestampSigner()>>> value = signer.sign('hello')>>> value'hello:1NMg5H:oPVuCqlJWmChm1rA2lyTUtelC-c'>>> signer.unsign(value)u'hello'>>> signer.unsign(value, max_age=10)...SignatureExpired: Signature age 15.5289158821 > 10 seconds>>> signer.unsign(value, max_age=20)u'hello'
class TimestampSigner(key=Nonesep=':'salt=None)
sign(value)

Sign value and append current timestamp to it.

unsign(valuemax_age=None)

Checks if value was signed less than max_age seconds ago, otherwise raises SignatureExpired.

Protecting complex data structures

If you wish to protect a list, tuple or dictionary you can do so using the signing module’s dumps and loads functions. These imitate Python’s pickle module, but use JSON serialization under the hood. JSON ensures that even if your SECRET_KEY is stolen an attacker will not be able to execute arbitrary commands by exploiting the pickle format.:

★ 保护复杂的数据结构,可以使用 dumps 模块和 loads 模块。 它们仿造了 Python 的pickle模块,但是使用了序列化的JSON。JSON确保即使SECRET_KEY被盗也不能用来执行任何命令

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

Returns URL-safe, sha1 signed base64 compressed JSON string. Serialized object is signed using TimestampSigner.

loads(stringkey=Nonesalt='django.core.signing'max_age=None)

Reverse of dumps(), raises BadSignature if signature fails. Checks max_age (in seconds) if given.


0 0
原创粉丝点击