Проверка подписи не работает при использовании асимметричного ключа, сгенерированного GCPJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Проверка подписи не работает при использовании асимметричного ключа, сгенерированного GCP

Сообщение Anonymous »

В моем загрузочном приложении Spring есть фильтр, который генерирует подпись для каждого ответа. Я создал асимметричный ключ в GCP (сгенерированный самим GCP)
Алгоритм ключа — 2048-битный ключ RSA PSS Padding — дайджест SHA256
Вот мой класс, который выполняет подписание и проверку. Проверка будет перенесена во внешний интерфейс, но пока, поскольку это всего лишь тест, я добавил все в один класс:

Код: Выделить всё

@Configuration
@Slf4j
public class ResponseFilterConfig {
GcpKmsConfiguration gcpKmsConfiguration;
private CryptoKeyVersionName asymmetricSignKeyForAPI;
@Autowired
KeyManagementServiceClient keyManagementServiceClient;
@Autowired
GcpKmsProperties gcpKmsProperties;
@Autowired
GCPKeyUseCase gcpKeyUseCase;

public ResponseFilterConfig(GcpKmsConfiguration gcpKmsConfiguration) {
this.gcpKmsConfiguration = gcpKmsConfiguration;
this.asymmetricSignKeyForAPI = gcpKmsConfiguration.asymmetricSignKeyForAPI();
}

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnWebApplication
public Filter responseLoggingFilter() {
return (request, response, chain) -> {
HttpServletRequest httpRequest = (HttpServletRequest) request;
boolean isFilterAllowed = shouldNotFilter(httpRequest);
HttpServletResponse httpResponse = (HttpServletResponse) response;
ContentCachingResponseWrapper responseCacheWrapperObject = new ContentCachingResponseWrapper(httpResponse);
chain.doFilter(request, responseCacheWrapperObject);

byte[] responseArray = responseCacheWrapperObject.getContentAsByteArray();
String responseStr = new String(responseArray, responseCacheWrapperObject.getCharacterEncoding());

var dataToSign = httpResponse.getStatus() + responseStr;
var signedData = signPayloadWithGcp(dataToSign);
if (!isFilterAllowed) {
httpResponse.addHeader("digital-signature", signedData);
}
responseCacheWrapperObject.copyBodyToResponse();
};
}

private String signPayloadWithGcp(String payload) throws IOException {
byte[] plaintext = payload.getBytes(StandardCharsets.UTF_8);
MessageDigest sha256;
AsymmetricSignResponse result;
try {
sha256 = MessageDigest.getInstance("SHA-256");
byte[] hash = sha256.digest(plaintext);
Digest digest = Digest.newBuilder().setSha256(ByteString.copyFrom(hash)).build();
result = keyManagementServiceClient.asymmetricSign(asymmetricSignKeyForAPI, digest);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Error signing payload with GCP", e);
}

String s = Base64.getEncoder().encodeToString(result.getSignature().toByteArray());

//for test verify the signature
try {
var res = verifySignature(s, payload);
log.info("Signature verification result: {}", res);
} catch (Exception e) {
log.error("Exception", e);
}
return s;
}

private boolean verifySignature(String signedData, String payload) throws Exception {
byte[] signatureBytes = Base64.getDecoder().decode(signedData);

byte[] plaintext = payload.getBytes(StandardCharsets.UTF_8);

// Get the public key.
com.google.cloud.kms.v1.PublicKey publicKey = fetchPublicKey();

// Convert the public PEM key to a DER key (see helper below).
byte[] derKey = convertPemToDer(publicKey.getPem());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);
java.security.PublicKey rsaKey = KeyFactory.getInstance("RSA").generatePublic(keySpec);

// Verify the 'RSA_SIGN_PKCS1_2048_SHA256' signature.
// For other key algorithms:
// http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature
Signature rsaVerify = Signature.getInstance("SHA256withRSA");
rsaVerify.initVerify(rsaKey);
rsaVerify.update(plaintext);

// Verify the signature.
boolean verified = rsaVerify.verify(signatureBytes);
System.out.printf("Signature verified: %s", verified);
return verified;
}

private byte[] convertPemToDer(String pem) {
BufferedReader bufferedReader = new BufferedReader(new StringReader(pem));
String encoded =
bufferedReader
.lines()
.filter(line -> !line.startsWith("-----BEGIN") &&  !line.startsWith("-----END"))
.collect(Collectors.joining());
return Base64.getDecoder().decode(encoded);
}

// Method to fetch public key from Google Cloud KMS
private com.google.cloud.kms.v1.PublicKey fetchPublicKey() throws IOException {
return gcpKeyUseCase.getPublicKey2(gcpKmsProperties.getProjectId(), gcpKmsProperties.getLocationId(), gcpKmsProperties.getSigningKeyRing(), gcpKmsProperties.getApiSignKey(), gcpKmsProperties.getApiSignKeyVersion());
}

protected boolean shouldNotFilter(HttpServletRequest request) {
String requestURI = request.getRequestURI();
return requestURI.contains("actuator") || requestURI.contains("open-api") || requestURI.contains("swagger") || requestURI.contains("/api/sign-key");
}

}

Проблема в том, что результат проверки по какой-то причине всегда имеет значение false. Есть какие-нибудь предложения о том, в чем может быть проблема в этом коде?
Пример полезной нагрузки:

Код: Выделить всё

200{"cards":[{"id":"69","referenceId":"89000901","number":"4459XXXXXXXX0901","status":"OPEN","expiryDate":"0528","modifiedAt":"2024-03-27T10:31:23","customerId":"36","nameOnCard":"Bora Duran","isPinCreated":false}]}
Пример подписи в заголовке ответа:

Код: Выделить всё

R8e+LjoD1GDVhXB8ZqzS+22Lf2SIADU3nCKHtHfJ6la5trSwAplyVmnKl9kT79yZO/bBaXUT25yyVEIicj/um71Ja5czl0DbWcF48oJNVpN1Hol0TJTQOMbKtBhN63H97Pir4u1SLEC9yF2Xkhvuf0fmM4tVcSqnfwZymNnU6TpKGnF7WGhulrW4esGsKXw2zjGIhSfSkZNv74VOy2c+FUX3tTD/oDA9QtV2mQdCPXhiFrh9h9Ukn2u2ysOzGuhmnhFqP98tzNRBjftijv2ZiSdRDm5sqsc2kREp/33DrQUmFe4ywBmDS6l6yI2oCWfTjXQDdLXTvRGh9rRU8zOynQ==
Вот документация, которой я следил:
Создание и проверка цифровых подписей

Подробнее здесь: https://stackoverflow.com/questions/784 ... ted-by-gcp
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»