import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Regions; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.services.kms.model.GetPublicKeyRequest; import com.amazonaws.services.kms.model.SignRequest; import com.amazonaws.util.BinaryUtils; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import org.web3j.crypto.ECDSASignature; import org.web3j.crypto.Hash; import org.web3j.crypto.Keys; import org.web3j.crypto.Sign; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.security.\*; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; @Slf4j public class AwsKmsTest { private static final String keyId = "****"; AWSKMS kmsClient = AWSKMSClientBuilder.standard() .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("****", "*****"))) .withRegion(Regions.AP_NORTHEAST_1) .build(); static { if (Security.getProvider("BC") == null) { Security.addProvider(new BouncyCastleProvider()); } } @Test public void publicKey() throws Exception { BCECPublicKey publicKey = (BCECPublicKey) getPublicKey(); System.out.println(Keys.getAddress(pubKeyToBigInter(publicKey))); } @Test public void sign() throws Exception { String msg = "hi"; byte[] Bytes = msg.getBytes(StandardCharsets.UTF_8); byte[] digestBytes = MessageDigest.getInstance("SHA-256").digest(Bytes); SignRequest signRequest = new SignRequest(); signRequest.setKeyId(keyId); signRequest.setMessage(ByteBuffer.wrap(digestBytes)); signRequest.setMessageType("DIGEST"); signRequest.setSigningAlgorithm("ECDSA_SHA_256"); ByteBuffer signatureB = kmsClient.sign(signRequest).getSignature(); BCECPublicKey publicKey = (BCECPublicKey) getPublicKey(); Signature signature = Signature.getInstance("SHA256withECDSA"); signature.initVerify(publicKey); signature.update(Bytes); if (signature.verify(signatureB.array())) { ECDSASignature ecdsaSignature = parseDERSequence(signatureB.array()); //throw exception:Could not construct a recoverable key. Are your credentials valid? Sign.SignatureData signMessage = Sign.createSignatureData(ecdsaSignature, pubKeyToBigInter(publicKey), Hash.sha3(Bytes)); System.out.println("0x" + Hex.toHexString(signMessage.getR()) + Hex.toHexString(signMessage.getS()) + Hex.toHexString(signMessage.getV())); } } public static BigInteger pubKeyToBigInter(BCECPublicKey publicKey) { byte[] publicKeyBytes = publicKey.getQ().getEncoded(false); return new BigInteger(1, Arrays.copyOfRange(publicKeyBytes, 1, publicKeyBytes.length)); } public PublicKey getPublicKey() throws Exception { GetPublicKeyRequest publicKeyRequest = new GetPublicKeyRequest(); publicKeyRequest.setKeyId(keyId); ByteBuffer publicKeyByteBuffer = kmsClient.getPublicKey(publicKeyRequest).getPublicKey(); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(BinaryUtils.copyBytesFrom(publicKeyByteBuffer)); KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC"); return keyFactory.generatePublic(keySpec); } private ECDSASignature parseDERSequence(byte[] derEncoded) throws IOException { ASN1InputStream asn1InputStream = new ASN1InputStream(derEncoded); ASN1Sequence asn1Sequence = (ASN1Sequence) asn1InputStream.readObject(); ASN1Integer r = (ASN1Integer) asn1Sequence.getObjectAt(0); ASN1Integer s = (ASN1Integer) asn1Sequence.getObjectAt(1); BigInteger rValue = r.getPositiveValue(); BigInteger sValue = s.getPositiveValue(); return new ECDSASignature(rValue, sValue); } } Sign.createSignatureData(ecdsaSignature,pubKeyToBigInter(publicKey),Hash.sha3(Bytes)); throw a exception:Could not construct a recoverable key. Are your credentials valid?
It can be roughly confirmed that the method parseDERSequence returns incorrect f and s values, resulting in failure. Does anyone know how to solve it