2

给定一个 RSA 私钥...

-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAMpZrx0gTluJEu6+fop1e60lwbnlBD6kHvoRx85GBhUgD8SQknjc
LcU2qqM/pV9ZX8MV8x49h2mzrmRyH7kDmpcCAwEAAQJAYf2GYMt5Rrids4IKk5CL
IPFs3FH8eT1PRvh/UvP0FBwDMZu/Q4m+3PNTM3ARQhFuCvWgCalMmZkyVx0HYRLe
4QIhAOaaQm+b/bSoHqolvVTcyfBL09rrLFZhgGkETX3R6cVRAiEA4KLdUm97YBxP
T6/jkn/P7K8SUWEO9o9u8Bif1UKQB2cCIETqoSQ92EqfW9q5wKWV/nvkDYKFehCu
vvOjp40MqPKhAiA2sPBZpbLQD5Rvvk8V1/Bzm5xGG+9csEc+RYCEl5QheQIhAKgi
Xb3zY9lqtpX/mgTIrW6RPB3GocviJOibqtpfNxRU
-----END RSA PRIVATE KEY-----

无装甲,base64解码给出......

30 82 01 3a 02 01 00 02 41 00 ca 59 af 1d 20 4e 5b 89 12 ee be 7e 8a 75 7b ad 25 c1 b9 e5 04 3e 
a4 1e fa 11 c7 ce 46 06 15 20 0f c4 90 92 78 dc 2d c5 36 aa a3 3f a5 5f 59 5f c3 15 f3 1e 3d 87 
69 b3 ae 64 72 1f b9 03 9a 97 02 03 01 00 01 02 40 61 fd 86 60 cb 79 46 b8 9d b3 82 0a 93 90 8b 
20 f1 6c dc 51 fc 79 3d 4f 46 f8 7f 52 f3 f4 14 1c 03 31 9b bf 43 89 be dc f3 53 33 70 11 42 11 
6e 0a f5 a0 09 a9 4c 99 99 32 57 1d 07 61 12 de e1 02 21 00 e6 9a 42 6f 9b fd b4 a8 1e aa 25 bd 
54 dc c9 f0 4b d3 da eb 2c 56 61 80 69 04 4d 7d d1 e9 c5 51 02 21 00 e0 a2 dd 52 6f 7b 60 1c 4f 
4f af e3 92 7f cf ec af 12 51 61 0e f6 8f 6e f0 18 9f d5 42 90 07 67 02 20 44 ea a1 24 3d d8 4a 
9f 5b da b9 c0 a5 95 fe 7b e4 0d 82 85 7a 10 ae be f3 a3 a7 8d 0c a8 f2 a1 02 20 36 b0 f0 59 a5 
b2 d0 0f 94 6f be 4f 15 d7 f0 73 9b 9c 46 1b ef 5c b0 47 3e 45 80 84 97 94 21 79 02 21 00 a8 22 
5d bd f3 63 d9 6a b6 95 ff 9a 04 c8 ad 6e 91 3c 1d c6 a1 cb e2 24 e8 9b aa da 5f 37 14 54 

我从中提取了所有数字,放入一个数组中......

[ '00',
  '00ca59af1d204e5b8912eebe7e8a757bad25c1b9e5043ea41efa11c7ce460615200fc4909278dc2dc536aaa33fa55f595fc315f31e3d8769b3ae64721fb9039a97',
  '010001',
  '61fd8660cb7946b89db3820a93908b20f16cdc51fc793d4f46f87f52f3f4141c03319bbf4389bedcf35333701142116e0af5a009a94c999932571d076112dee1',
  '00e69a426f9bfdb4a81eaa25bd54dcc9f04bd3daeb2c56618069044d7dd1e9c551',
  '00e0a2dd526f7b601c4f4fafe3927fcfecaf1251610ef68f6ef0189fd542900767',
  '44eaa1243dd84a9f5bdab9c0a595fe7be40d82857a10aebef3a3a78d0ca8f2a1',
  '36b0f059a5b2d00f946fbe4f15d7f0739b9c461bef5cb0473e45808497942179',
  '00a8225dbdf363d96ab695ff9a04c8ad6e913c1dc6a1cbe224e89baada5f371454' 
]

我不明白的是...

1. 为什么提取的值有的有前导00,有的没有?

2. 第一个值 ( 00) 的用途是什么?这对我来说似乎是多余的。

我想知道的原因是我想在 javascript 中生成 RSA 密钥。我正在生成所需的数字,但我不知道它们什么时候应该有前导00s。

编辑

另外,我不太明白整个事情的第一部分......

30 82 01 3a

我知道这01 3a是消息其余部分的长度,但我不知道30 82代表什么。

3.30 82解码密钥的开头是什么?

4

2 回答 2

2

大多数答案都在这里: http: //pumka.net/2009/12/19/reading-writing-and-converting-rsa-keys-in-pem-der-publickeyblob-and-privatekeyblob-formats/

  1. 请注意,DER 中的许多整数值都以零字节开头。这是因为 ASN.1 标准要求如果多字节整数的第一位设置为 1,则在多字节整数的开头添加零字节。

  2. @Gwyn 的回答后更新(http://www.regular-expressions.info/conditional.html它是版本号,目前仅用于区分多素数和普通,但也将用于区分 RSA 的修订版规格

  3. 来自: http: //msdn.microsoft.com/en-us/library/windows/desktop/bb648645 (v=vs.85).aspx和:http: //msdn.microsoft.com/en-us/library/ windows/桌面/bb648641(v=vs.85).aspx

SEQUENCE 包含一种或多种类型的有序字段。它被编码成一个以 0x30 标记字节开头的 TLV 三元组。

...

如果 SEQUENCE 包含少于 128 个字节,则 TLV 三元组的 Length 字段只需要一个字节来指定内容长度。如果超过 127 个字节,长度字段的第 7 位设置为 1,第 6 到 0 位指定用于标识内容长度的附加字节数。

编码...

这是 javascript 代码,有点粗糙,但是如何生成 RSA 密钥的工作证明,可以使用 javascript 与 OpenSSL 互操作,以及输入密钥生成所需的数字......

function hex2b64(h) {
  var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var b64pad="=";

  var i;
  var c;
  var ret = "";
  for(i = 0; i+3 <= h.length; i+=3) {
    c = parseInt(h.substring(i,i+3),16);
    ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
  }
  if(i+1 == h.length) {
    c = parseInt(h.substring(i,i+1),16);
    ret += b64map.charAt(c << 2);
  }
  else if(i+2 == h.length) {
    c = parseInt(h.substring(i,i+2),16);
    ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
  }
  while((ret.length & 3) > 0) ret += b64pad;
  return ret;
}

var private_key = "-----BEGIN RSA PRIVATE KEY-----\n"+
"MIIBOgIBAAJBAMpZrx0gTluJEu6+fop1e60lwbnlBD6kHvoRx85GBhUgD8SQknjc\n"+
"LcU2qqM/pV9ZX8MV8x49h2mzrmRyH7kDmpcCAwEAAQJAYf2GYMt5Rrids4IKk5CL\n"+
"IPFs3FH8eT1PRvh/UvP0FBwDMZu/Q4m+3PNTM3ARQhFuCvWgCalMmZkyVx0HYRLe\n"+
"4QIhAOaaQm+b/bSoHqolvVTcyfBL09rrLFZhgGkETX3R6cVRAiEA4KLdUm97YBxP\n"+
"T6/jkn/P7K8SUWEO9o9u8Bif1UKQB2cCIETqoSQ92EqfW9q5wKWV/nvkDYKFehCu\n"+
"vvOjp40MqPKhAiA2sPBZpbLQD5Rvvk8V1/Bzm5xGG+9csEc+RYCEl5QheQIhAKgi\n"+
"Xb3zY9lqtpX/mgTIrW6RPB3GocviJOibqtpfNxRU\n"+
"-----END RSA PRIVATE KEY-----";

// these numbers have been extracted from the given RSA private key
numbers = ['00',
  'ca59af1d204e5b8912eebe7e8a757bad25c1b9e5043ea41efa11c7ce460615200fc4909278dc2dc536aaa33fa55f595fc315f31e3d8769b3ae64721fb9039a97',
  '010001',
  '61fd8660cb7946b89db3820a93908b20f16cdc51fc793d4f46f87f52f3f4141c03319bbf4389bedcf35333701142116e0af5a009a94c999932571d076112dee1',
  'e69a426f9bfdb4a81eaa25bd54dcc9f04bd3daeb2c56618069044d7dd1e9c551',
  'e0a2dd526f7b601c4f4fafe3927fcfecaf1251610ef68f6ef0189fd542900767',
  '44eaa1243dd84a9f5bdab9c0a595fe7be40d82857a10aebef3a3a78d0ca8f2a1',
  '36b0f059a5b2d00f946fbe4f15d7f0739b9c461bef5cb0473e45808497942179',
  'a8225dbdf363d96ab695ff9a04c8ad6e913c1dc6a1cbe224e89baada5f371454' ]

var data = ""

// loop through all the numbers
for(i in numbers){
  var item = numbers[i]

  // if the first binary bit is 1 (if the first hex pair is greater than 127)
  // add a `00` prefix, as ASN1 demands
  if(parseInt(item.match(/^../),16) > 127){ item = "00"+item }

  // calculate the length
  var len = ("0"+(item.length/2).toString(16)).replace(/.(..)/,"$1")

  // build data string, the `02` is ASN1 code for string
  data += "02"+len+item

  // can check all the input data here
  // console.log("02", len, item)
}

// calculate the length of all the data
var datalen = (data.length/2).toString(16)
// add leading `0` if required to ensure hex pairs
if(datalen.length % 2 == 1){ datalen = "0"+datalen }

// set the extra bits to define the length if required, or make it empty
var exlen = parseInt(datalen,16) >= 128 ? (datalen.length/2 + 128).toString(16) : ''

// create the full data string
var full_data = "30"+exlen+datalen+data

// encode the data
var encoded = hex2b64(full_data)

// split it into lines no longer than 64 characters
var lines = encoded.match(/.{1,64}/g)

// add the armour
lines.unshift("-----BEGIN RSA PRIVATE KEY-----")
lines.push("-----END RSA PRIVATE KEY-----")

// join it all together
var generated_key = lines.join("\n")

// check if the generated key matches the expected key
console.log(generated_key == private_key)
于 2013-02-13T12:42:45.940 回答
1

只是回答 2,因为其他问题已经解决,第一个 00 是版本字段。在此处使用 ASN.1 解码器来解码 Base64 或十六进制以显示 9 个整数的序列。您需要检查规格(请参阅 A.1.2)以了解它们是什么,虽然虽然不是确定的,但 Wikipedia在此处提供了一些信息

于 2013-02-21T23:15:20.017 回答