하드웨어 보안 모듈의 PKCS # 11 API에 대해 PKCS # 11 Java Wrapper를 사용하여 DSA로 SHA-256 해시에 서명하려고합니다. 이를 위해 메커니즘 CKM_DSA를 선택하고 토큰에서 해당 DSA 키를로드하고 데이터 (바이트 배열로 읽음)를 서명했습니다. 테스트를 위해 사용하는 키의 길이는 1024 비트입니다.OpenSSL에서 PKCS # 11에 의해 생성 된 DSA 서명 확인
모두 잘 작동하는 것으로 보인다 : 키가 로딩되면, Session.sign()를 말한다 이는 PKCS에 사양을 # 11의 대응하는 길이 (40)의 바이트 [] 배열 수율 :
"를 들어 이 메커니즘의 목적하는 DSA 서명은 DSA의 연결에 해당하는 40 바이트의 문자열 각각 제 최상위 바이트를 나타내는, (R) 및 값 S이다.는 "
이제 I 사용이 서명을 검증 할 openSSL, ie, using
openssl dgst -d -sha256 -verify ${PUBLIC_KEY} -signature signature.der <raw input file>
,691,363,210
이 제가
a)은 OpenSSL
B)를 사용하여 서명을 작성 bouncycastle를 사용 ASN1 DER 인코딩 순서로 결과를 암호화하여 서명을 생성하는 경우 작동한다.
이제 PKCS # 11 서명과 동일한 작업을 수행하려고합니다. 내 질문은 :이 40 바이트 배열을 포맷하는 방법은 무엇입니까? 그것이 내가 R을 생산하는 경우 작동 bouncycastle 다른 소프트웨어 키와 직접이야 때문에
//sign data
byte[] signedData = this.pkcs11Session.sign(dataToSign);
//convert result
byte[] r = new byte[20];
byte[] s = new byte[20];
System.arraycopy(signedData, 0, r, 0, 20);
System.arraycopy(signedData, 19, s, 0, 20);
//encode result
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
return new DERSequence(v).getEncoded(ASN1Encoding.DER);
인코딩 부분은 올바른 것 같습니다 : 나는 다음 시도했다. 게다가 openssl은 입력 형식을 받아들이지 만 오류가있는 경우 가끔 검증에 실패하고 때로는 "검증 실패"와 함께 실패합니다.
따라서 PKCS # 11 서명을 r 및 s로 변환하는 것이 잘못되었다고 가정합니다. 누군가 실수를 찾는 것을 도와 줄 수 있습니까?
전체 스택 추적을 요청한 주석을 포함하여 주석이 제거되었습니다. 전체 스택 추적을 제공하고 일부 테스트 데이터와 키를 제공하는 것이 바람직합니다. –
두 번째 배열 복사가 19 대신에 위치 20에서 시작해야합니까? 당신은 r의 마지막 바이트가 두 번 있고, s의 마지막 바이트를 얻지 않은 것처럼 보입니다. – bartonjs