【问题标题】:Get the big-endian byte sequence of integer in Python在Python中获取整数的大端字节序列
【发布时间】:2015-08-27 08:25:15
【问题描述】:

根据这篇文章:How to return RSA key in jwks_uri endpoint for OpenID Connect Discovery

我需要base64url-encode这两个数字的八位字节值

n = 124692971944797177402996703053303877641609106436730124136075828918287037758927191447826707233876916396730936365584704201525802806009892366608834910101419219957891196104538322266555160652329444921468362525907130134965311064068870381940624996449410632960760491317833379253431879193412822078872504618021680609253

e = 65537

“n”(模数)参数包含 RSA 公钥的模值。它表示为 Base64urlUInt 编码的值。 请注意,实施者发现一些密码库 在它们的模数表示前面加上一个额外的零值八位字节 例如,返回一个 2048 位密钥的 257 个八位字节,而不是 超过 256. 使用此类库的实现将需要采取 注意省略 base64url 编码的额外八位字节 表示。

“e”(指数)参数包含 RSA 的指数值 公钥。它表示为 Base64urlUInt 编码的值。 例如,当表示值 65537 时,八位字节序列 要进行 base64url 编码,必须由三个八位字节 [1, 0, 1] 组成; 该值的结果表示为“AQAB”。

例如,有效的编码应如下所示:https://www.googleapis.com/oauth2/v3/certs

¿我如何在 Python 中做到这一点?

【问题讨论】:

  • 你用的是什么 Python 版本?

标签: python integer rsa


【解决方案1】:

这里有一段不同的 Python 代码,取自 rsalette

def bytes_to_int(data):
    """Convert bytes to an integer"""
    hexy = binascii.hexlify(data)
    hexy = b'0'*(len(hexy)%2) + hexy
    return int(hexy, 16)

def b64_to_int(data):
    """Convert urlsafe_b64encode(data) to an integer"""
    return bytes_to_int(urlsafe_b64decode(data))

def int_to_bytes(integer):
    hexy = as_binary('%x' % integer)
    hexy = b'0'*(len(hexy)%2) + hexy
    data = binascii.unhexlify(hexy)
    return data

def int_to_b64(integer):
    """Convert an integer to urlsafe_b64encode() data"""
    return urlsafe_b64encode(int_to_bytes(integer))

def as_binary(text):
    return text.encode('latin1')

【讨论】:

    【解决方案2】:

    在寻找解决此问题的最佳方法后,使用pyjwkest 似乎是一个好方法,而不是创建我自己的函数。

    pip install pyjwkest
    

    然后我们为此使用long_to_base64函数

    >>> from jwkest import long_to_base64
    >>> long_to_base64(65537)
    'AQAB'
    

    【讨论】:

      【解决方案3】:

      不幸的是 pack() 不支持这么大的数字,而 int.to_bytes() 仅在 Python 3 中支持,所以我们必须在编码之前自己打包它们。受到this post 的启发,我首先将其转换为十六进制字符串:

      import math
      import base64
      
      def Base64urlUInt(n):
          # fromhex() needs an even number of hex characters,
          # so when converting our number to hex we need to give it an even
          # length. (2 characters per byte, 8 bits per byte)
          length = int(math.ceil(n.bit_length() / 8.0)) * 2
          fmt = '%%0%dx' % length
          packed = bytearray.fromhex(fmt % n)
          return base64.urlsafe_b64encode(packed).rstrip('=')
      

      导致:

      n = 124692971944797177402996703053303877641609106436730124136075828918287037758927191447826707233876916396730936365584704201525802806009892366608834910101419219957891196104538322266555160652329444921468362525907130134965311064068870381940624996449410632960760491317833379253431879193412822078872504618021680609253
      e = 65537
      
      Base64urlUInt(n) == 'sZGVa39dSmJ5c7mbOsJZaq62MVjPD3xNPb-Aw3VJznk6piF5GGgdMoQmAjNmANVBBpPUyQU2SEHgXQvp6j52E662umdV2xU-1ETzn2dW23jtdTFPHRG4BFZz7m14MXX9i0QqgWVnTRy-DD5VITkFZvBqCEzWjT_y47DYD2Dod-U'
      Base64urlUInt(e) == 'AQAB'
      

      【讨论】:

        猜你喜欢
        • 2012-12-29
        • 1970-01-01
        • 2015-11-20
        • 1970-01-01
        • 2010-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多