All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alipay.api.kms.aliyun.AliyunKMSClient Maven / Gradle / Ivy

package com.alipay.api.kms.aliyun;

import com.alipay.api.internal.util.codec.Base64;
import com.alipay.api.kms.aliyun.models.AsymmetricSignRequest;
import com.alipay.api.kms.aliyun.models.AsymmetricSignResponse;
import com.alipay.api.kms.aliyun.models.GetPublicKeyRequest;
import com.alipay.api.kms.aliyun.models.GetPublicKeyResponse;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECFieldElement;

import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class AliyunKMSClient extends AliyunRpcClient {
    private PublicKey publicKey = null;
    private static final Map digestAlgs = new HashMap();
    private static final Map namedCurves = new HashMap();

    public AliyunKMSClient(String endpoint, String accessKeyId, String accessKeySecret) {
        super(endpoint, accessKeyId, accessKeySecret);
    }

    public AliyunKMSClient(String endpoint, String accessKeyId, String accessKeySecret, String stsToken) {
        super(endpoint, accessKeyId, accessKeySecret, stsToken);
    }

    public AliyunKMSClient(String endpoint, String accessKeyId, String accessKeySecret, String roleArn, String roleSessionName) {
        super(endpoint, accessKeyId, accessKeySecret, roleArn, roleSessionName);
    }

    public AliyunKMSClient(String endpoint, String accessKeyId, String accessKeySecret, String roleArn, String roleSessionName, String policy) {
        super(endpoint, accessKeyId, accessKeySecret, roleArn, roleSessionName, policy);
    }

    public AliyunKMSClient(String endpoint, String roleName) {
        super(endpoint, roleName);
    }

    private PublicKey getPublicKey(String keyId, String keyVersionId) throws Exception {
        GetPublicKeyRequest request = new GetPublicKeyRequest();
        request.setKeyId(keyId);
        request.setKeyVersionId(keyVersionId);
        GetPublicKeyResponse response = getAcsResponse(request);

        String pemKey = String.valueOf(response.getPublicKey());
        pemKey = pemKey.replaceFirst("-----BEGIN PUBLIC KEY-----", "");
        pemKey = pemKey.replaceFirst("-----END PUBLIC KEY-----", "");
        pemKey = pemKey.replaceAll("\\s", "");
        byte[] derKey = Base64.decodeBase64String(pemKey);

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(derKey);
        Security.addProvider(new BouncyCastleProvider());
        return KeyFactory.getInstance("EC", "BC").generatePublic(keySpec);
    }

    private byte[] getZ(ECPublicKeyParameters ecPublicKeyParameters, ECDomainParameters ecDomainParameters) {
        Digest digest = new SM3Digest();
        digest.reset();

        String userID = "1234567812345678";
        addUserID(digest, userID.getBytes());

        addFieldElement(digest, ecDomainParameters.getCurve().getA());
        addFieldElement(digest, ecDomainParameters.getCurve().getB());
        addFieldElement(digest, ecDomainParameters.getG().getAffineXCoord());
        addFieldElement(digest, ecDomainParameters.getG().getAffineYCoord());
        addFieldElement(digest, ecPublicKeyParameters.getQ().getAffineXCoord());
        addFieldElement(digest, ecPublicKeyParameters.getQ().getAffineYCoord());

        byte[] result = new byte[digest.getDigestSize()];
        digest.doFinal(result, 0);
        return result;
    }

    private void addUserID(Digest digest, byte[] userID) {
        int len = userID.length * 8;
        digest.update((byte) (len >> 8 & 0xFF));
        digest.update((byte) (len & 0xFF));
        digest.update(userID, 0, userID.length);
    }

    private void addFieldElement(Digest digest, ECFieldElement v) {
        byte[] p = v.getEncoded();
        digest.update(p, 0, p.length);
    }

    private byte[] calcSM3Digest(PublicKey pubKey, byte[] message, String algorithm) {
        X9ECParameters x9ECParameters = GMNamedCurves.getByName(namedCurves.get(algorithm));
        ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
        BCECPublicKey localECPublicKey = (BCECPublicKey) pubKey;
        ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(localECPublicKey.getQ(), ecDomainParameters);
        byte[] z = getZ(ecPublicKeyParameters, ecDomainParameters);
        Digest digest = new SM3Digest();
        digest.update(z, 0, z.length);
        digest.update(message, 0, message.length);
        byte[] result = new byte[digest.getDigestSize()];
        digest.doFinal(result, 0);
        return result;
    }

    /**
     * 获取阿里云KMS签名
     * 阿里云KMS签名接口文档:
     * https://help.aliyun.com/document_detail/148132.html?spm=a2c4g.11186623.6.610.3fd17338c716si
     *
     * @param keyId        阿里云KMS非对称密钥ID
     * @param keyVersionId 阿里云KMS非对称密钥版本ID
     * @param algorithm    阿里云KMS签名算法
     * @param message      待签名的内容
     * @return 签名值的Base64串
     */
    private String asymmetricSign(String keyId, String keyVersionId, String algorithm, byte[] message) throws Exception {
        byte[] digest;
        if (algorithm.equals("SM2DSA")) {
            if (this.publicKey == null) {
                this.publicKey = getPublicKey(keyId, keyVersionId);
            }
            digest = calcSM3Digest(this.publicKey, message, algorithm);
        } else {
            digest = MessageDigest.getInstance(digestAlgs.get(algorithm)).digest(message);
        }
        AsymmetricSignRequest request = new AsymmetricSignRequest();
        request.setKeyId(keyId);
        request.setKeyVersionId(keyVersionId);
        request.setAlgorithm(algorithm);
        request.setDigest(Base64.encodeBase64String(digest));
        AsymmetricSignResponse response = getAcsResponse(request);
        return response.getValue();
    }

    /**
     * 计算签名
     *
     * @param keyId        阿里云KMS非对称密钥ID
     * @param keyVersionId 阿里云KMS非对称密钥版本ID
     * @param algorithm    阿里云KMS签名算法
     * @param message      待签名的内容
     * @return 签名值的Base64串
     */
    public String sign(String keyId, String keyVersionId, String algorithm, byte[] message) throws Exception {
        return asymmetricSign(keyId, keyVersionId, algorithm, message);
    }

    static {
        digestAlgs.put("RSA_PKCS1_SHA_256", "SHA-256");
        digestAlgs.put("RSA_PSS_SHA_256", "SHA-256");
        digestAlgs.put("ECDSA_SHA_256", "SHA-256");

        namedCurves.put("SM2DSA", "sm2p256v1");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy