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

com.github.joekerouac.common.tools.crypto.impl.BCECDHKeyExchangeSpi Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package com.github.joekerouac.common.tools.crypto.impl;

import java.math.BigInteger;
import java.security.Provider;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

import com.github.joekerouac.common.tools.constant.Const;
import com.github.joekerouac.common.tools.constant.ExceptionProviderConst;
import com.github.joekerouac.common.tools.crypto.ECDHKeyExchangeSpi;
import com.github.joekerouac.common.tools.crypto.constant.NamedCurve;
import com.github.joekerouac.common.tools.util.Assert;

/**
 * 使用bouncycastle实现的ECDH密钥交换算法
 *
 * @since 1.0.0
 * @author JoeKerouac
 * @date 2022-10-14 14:37:00
 */
public class BCECDHKeyExchangeSpi extends AbstractECDHKeyExchangeSpi implements ECDHKeyExchangeSpi {

    private static final Map CACHE = new ConcurrentHashMap<>();

    @Override
    protected Provider provider() {
        return Const.BC_PROVIDER;
    }

    @Override
    protected KeySpec convertToPublicKeySpec(int curveId, byte[] publicKeyData) {
        ECDomainParameters domainParameters = getECDomainParameters(curveId);

        // 使用指定数据解析出ECPoint
        ECPoint Q = domainParameters.getCurve().decodePoint(publicKeyData);

        ECParameterSpec ecParameterSpec = internalGetECParameterSpec(curveId);
        return new ECPublicKeySpec(Q, ecParameterSpec);
    }

    @Override
    protected KeySpec convertToPrivateKeySpec(int curveId, byte[] privateKeyData) {
        ECParameterSpec ecParameterSpec = internalGetECParameterSpec(curveId);
        return new ECPrivateKeySpec(new BigInteger(privateKeyData), ecParameterSpec);
    }

    @Override
    protected AlgorithmParameterSpec getECParameterSpec(int curveId) {
        return internalGetECParameterSpec(curveId);
    }

    @Override
    protected int fieldSize(AlgorithmParameterSpec ecParamter) {
        if (!(ecParamter instanceof ECParameterSpec)) {
            throw new IllegalArgumentException("不支持的参数:" + ecParamter);
        }
        return ((ECParameterSpec)ecParamter).getCurve().getFieldSize();
    }

    /**
     * 根据curveId获取ECDomainParameters
     * 
     * @param curveId
     *            curveId
     * @return ECDomainParameters
     */
    private static ECDomainParameters getECDomainParameters(int curveId) {
        String curveName = getCurveName(curveId);

        X9ECParameters ecP = getX9ECParameters(curveName);

        return new ECDomainParameters(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(), ecP.getSeed());
    }

    /**
     * 根据curveId获取ECDomainParameters
     * 
     * @param curveId
     *            curveId
     * @return ECDomainParameters
     */
    private static ECParameterSpec internalGetECParameterSpec(int curveId) {
        String curveName = getCurveName(curveId);

        X9ECParameters ecP = getX9ECParameters(curveName);

        return new ECNamedCurveParameterSpec(curveName, ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(),
            ecP.getSeed());
    }

    /**
     * 根据曲线ID获取曲线名
     * 
     * @param curveId
     *            曲线ID
     * @return 曲线名
     */
    private static String getCurveName(int curveId) {
        String curveName = NamedCurve.getCurveName(curveId);
        Assert.notBlank(curveName, "不支持的 curveId: " + curveId, ExceptionProviderConst.IllegalArgumentExceptionProvider);
        return curveName;
    }

    /**
     * 根据曲线名获取曲线参数
     * 
     * @param curveName
     *            曲线名
     * @return 曲线参数
     */
    private static X9ECParameters getX9ECParameters(String curveName) {
        X9ECParameters ecP = CACHE.compute(curveName, (name, parameter) -> {
            if (parameter == null) {
                return SECNamedCurves.getByName(curveName);
            } else {
                return parameter;
            }
        });

        Assert.notNull(ecP, "不支持的 curveName: " + curveName, ExceptionProviderConst.IllegalArgumentExceptionProvider);
        return ecP;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy