문제

문자열, 서명 및 공개 키가 있으며 문자열의 서명을 확인하고 싶습니다. 키는 다음과 같습니다.

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfG4IuFO2h/LdDNmonwGNw5srW
nUEWzoBrPRF1NM8LqpOMD45FAPtZ1NmPtHGo0BAS1UsyJEGXx0NPJ8Gw1z+huLrl
XnAVX5B4ec6cJfKKmpL/l94WhP2v8F3OGWrnaEX1mLMoxe124Pcfamt0SPCGkeal
VvXw13PLINE/YptjkQIDAQAB
-----END PUBLIC KEY-----

나는 파이 크립토 문서를 잠시 동안 읽었지만 이런 종류의 열쇠로 RSAOBJ를 만드는 방법을 알 수는 없습니다. PHP를 알고 있다면 다음을 수행하려고합니다.

openssl_verify($data, $signature, $public_key, OPENSSL_ALGO_SHA1);

또한 용어에 대해 혼란 스러우면 알려주십시오.

도움이 되었습니까?

해결책

마커 사이의 데이터는 PKCS#1 rsapublickey를 포함하는 PKCS#8 Public Keyinfo의 ASN.1 Der-Encoding의 Base64 인코딩입니다.

그것은 많은 표준이며, 당신은 암호 라이브러리를 사용하여 그것을 해독하는 데 가장 적합합니다 (예 : m2crypto : Joeforker가 제안한). 다음을 형식에 대한 재미있는 정보로 취급하십시오.

원한다면 다음과 같이 해독 할 수 있습니다.

Base64-Decode 문자열 :

30819f300d06092a864886f70d010101050003818d0030818902818100df1b822e14eda1fcb74336
6a27c06370e6cad69d4116ce806b3d117534cf0baa938c0f8e4500fb59d4d98fb471a8d01012d54b
32244197c7434f27c1b0d73fa1b8bae55e70155f907879ce9c25f28a9a92ff97de1684fdaff05dce
196ae76845f598b328c5ed76e0f71f6a6b7448f08691e6a556f5f0d773cb20d13f629b6391020301
0001

이것은 다음의 der-encoding입니다.

   0 30  159: SEQUENCE {
   3 30   13:   SEQUENCE {
   5 06    9:     OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
  16 05    0:     NULL
            :     }
  18 03  141:   BIT STRING 0 unused bits, encapsulates {
  22 30  137:       SEQUENCE {
  25 02  129:         INTEGER
            :           00 DF 1B 82 2E 14 ED A1 FC B7 43 36 6A 27 C0 63
            :           70 E6 CA D6 9D 41 16 CE 80 6B 3D 11 75 34 CF 0B
            :           AA 93 8C 0F 8E 45 00 FB 59 D4 D9 8F B4 71 A8 D0
            :           10 12 D5 4B 32 24 41 97 C7 43 4F 27 C1 B0 D7 3F
            :           A1 B8 BA E5 5E 70 15 5F 90 78 79 CE 9C 25 F2 8A
            :           9A 92 FF 97 DE 16 84 FD AF F0 5D CE 19 6A E7 68
            :           45 F5 98 B3 28 C5 ED 76 E0 F7 1F 6A 6B 74 48 F0
            :           86 91 E6 A5 56 F5 F0 D7 73 CB 20 D1 3F 62 9B 63
            :           91
 157 02    3:         INTEGER 65537
            :         }
            :       }
            :   }

1024 비트 RSA 키의 경우 치료할 수 있습니다. "30819f300d06092a864886f70d010101050003818d00308189028181" 일정한 헤더로서, 00 바이트가 이어지고, RSA 계수의 128 바이트가 뒤 따릅니다. 그 후 95%가 얻을 수 있습니다. 0203010001, 이것은 0x10001 = 65537의 RSA 공개 지수를 의미합니다.

이 두 값을 사용할 수 있습니다 n 그리고 e RSAOBJ를 구성하는 튜플에서.

다른 팁

사용 M2Crypto. 다음은 OpenSSL에서 지원하는 RSA 및 기타 알고리즘을 확인하는 방법입니다.

pem = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfG4IuFO2h/LdDNmonwGNw5srW
nUEWzoBrPRF1NM8LqpOMD45FAPtZ1NmPtHGo0BAS1UsyJEGXx0NPJ8Gw1z+huLrl
XnAVX5B4ec6cJfKKmpL/l94WhP2v8F3OGWrnaEX1mLMoxe124Pcfamt0SPCGkeal
VvXw13PLINE/YptjkQIDAQAB
-----END PUBLIC KEY-----""" # your example key

from M2Crypto import BIO, RSA, EVP
bio = BIO.MemoryBuffer(pem)
rsa = RSA.load_pub_key_bio(bio)
pubkey = EVP.PKey()
pubkey.assign_rsa(rsa)

# if you need a different digest than the default 'sha1':
pubkey.reset_context(md='sha1')
pubkey.verify_init()
pubkey.verify_update('test  message')
assert pubkey.verify_final(signature) == 1

공개 키에는 모듈러스 (매우 긴 숫자, 1024 비트, 2058 비트, 4096 비트) 및 공개 키 지수 (훨씬 적은 숫자, 일반적으로 2에서 일부 전력보다 1보다 1 이상)가 포함되어 있습니다. 공개 키를 두 구성 요소로 나누는 방법을 찾아야합니다.

나는 Pycrypto에 대해 많이 알지 못하지만 서명을 확인하기 위해 문자열의 해시를 가져 가십시오. 이제 서명을 해독해야합니다. 읽으십시오 모듈 식 지수; 서명을 해독하는 공식은 다음과 같습니다 message^public exponent % modulus. 마지막 단계는 해시와 해독 된 서명이 동일한 지 확인하는 것입니다.

제 생각에는 에즈피 크립토 이것을 조금 더 쉽게 만들 수 있습니다. 높은 수준의 방법 열쇠 수업에는 문제가 해결되기를 희망하는이 두 가지 방법이 포함되어 있습니다.

  • VerifyString - 서명에 대해 문자열을 확인하십시오
  • importkey - 공개 키 가져 오기 (및 아마도 개인 키도)

라스무스 그 의견을 지적합니다 verifyString MD5를 사용하도록 하드 코딩되었으며,이 경우 Ezpycryto는 코드에 휩싸이지 않으면 Andrew를 도울 수 없습니다. 나는 연기한다 JoeForker의 대답: 고려하다 M2Crypto.

der decoding에 대한 자세한 내용.

der 인코딩은 항상 TLV 트리플렛 형식을 따릅니다. (태그, 길이, 값)

  • 태그 값의 유형 (예 : 데이터 구조)을 지정합니다.
  • 길이는이 값 필드가 차지하는 바이트 수를 지정합니다.
  • 값은 또 다른 트리플렛이 될 수있는 실제 값입니다.

태그는 기본적으로 값 필드에서 바이트 데이터를 해석하는 방법을 알려줍니다. Ans.1은 유형 시스템을 가지고 있으며, 예를 들어 0x02는 정수를 의미하며, 0x30은 순서 (하나 이상의 다른 유형 인스턴스의 순서가 정렬)를 의미합니다.

길이 프레젠테이션에는 특별한 논리가 있습니다.

  • 길이 <127 인 경우 L 필드는 하나의 바이트 만 사용하고 길이 숫자 값으로 직접 코딩됩니다.
  • 길이> 127 인 경우 L 필드의 첫 바이트에서 첫 번째 비트는 1이어야하고 나머지 7 비트는 값 필드의 길이를 지정하는 데 사용되는 다음 바이트의 수를 나타냅니다. 값, 실제로 값 자체의 바이트.

예를 들어, 다수의 256 바이트를 인코딩하고 싶다고해서 다음과 같을 것입니다.

02  82  01  00  1F  2F  3F  4F  …   DE  AD  BE  EF
  • 태그, 0x02는 숫자임을 의미합니다
  • 길이, 0x82, 그것의 비트 프레젠테이션은 1000 0010입니다. 즉, 다음 두 바이트는 실제로 값의 길이를 지정합니다. 이는 그의 0x0100이 값 필드의 길이가 256 바이트입니다.
  • 값, 1F에서 EF, 실제 256 바이트.

이제 당신의 예를보고 있습니다

30819f300d06092a864886f70d010101050003818d0030818902818100df1b822e14eda1fcb74336
6a27c06370e6cad69d4116ce806b3d117534cf0baa938c0f8e4500fb59d4d98fb471a8d01012d54b
32244197c7434f27c1b0d73fa1b8bae55e70155f907879ce9c25f28a9a92ff97de1684fdaff05dce
196ae76845f598b328c5ed76e0f71f6a6b7448f08691e6a556f5f0d773cb20d13f629b6391020301
0001

Rasmus Faber가 그의 대답에 넣은 것으로 해석합니다.

어쩌면 이것은 당신이 찾고있는 대답이 아니지만, 필요한 모든 것이 키를 비트로 바꾸는 것만이라면 Base64 인코딩 된 것처럼 보입니다. 를보세요 codecs 표준 파이썬 라이브러리의 모듈 (생각).

M2Crypto를 사용하면 위의 답변이 작동하지 않습니다. 다음은 테스트 된 예입니다.

import base64
import hashlib
import M2Crypto as m2

# detach the signature from the message if it's required in it (useful for url encoded data)
message_without_sign = message.split("&SIGN=")[0]
# decode base64 the signature
binary_signature = base64.b64decode(signature)
# create a pubkey object with the public key stored in a separate file
pubkey = m2.RSA.load_pub_key(os.path.join(os.path.dirname(__file__), 'pubkey.pem'))
# verify the key
assert pubkey.check_key(), 'Key Verification Failed'
# digest the message
sha1_hash = hashlib.sha1(message_without_sign).digest()
# and verify the signature
assert pubkey.verify(data=sha1_hash, signature=binary_signature), 'Certificate Verification Failed'

그리고 그것에 관한 것입니다

JoeForker가 제공 한 코드를 시도하지만 작동하지 않습니다. 여기 내 예제 코드가 있으며 잘 작동합니다.

from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA 
from Crypto.Hash import SHA

pem = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfG4IuFO2h/LdDNmonwGNw5srW
nUEWzoBrPRF1NM8LqpOMD45FAPtZ1NmPtHGo0BAS1UsyJEGXx0NPJ8Gw1z+huLrl
XnAVX5B4ec6cJfKKmpL/l94WhP2v8F3OGWrnaEX1mLMoxe124Pcfamt0SPCGkeal
VvXw13PLINE/YptjkQIDAQAB
-----END PUBLIC KEY-----""" # your example key

key = RSA.importKey(pem)
h = SHA.new(self.populateSignStr(params))
verifier = PKCS1_v1_5.new(key)
if verifier.verify(h, signature):
  print "verified"
else:
  print "not verified"
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top