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

com.klaytn.caver.utils.AccountKeyPublicUtils Maven / Gradle / Ivy

There is a newer version: 1.12.2-android
Show newest version
/*
 * Modifications copyright 2019 The caver-java Authors
 * Copyright 2016 Conor Svensson
 *
 * Licensed 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.
 *
 * This file is derived from web3j/crypto/src/main/java/org/web3j/crypto/Sign.java (2019/06/13).
 * Modified and improved for the caver-java development.
 */

package com.klaytn.caver.utils;

import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9IntegerConverter;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.math.ec.ECPoint;
import com.klaytn.caver.tx.account.AccountKeyPublic;
import org.web3j.utils.Numeric;

import java.math.BigInteger;

public class AccountKeyPublicUtils {

    public static final X9ECParameters CURVE_PARAMS = CustomNamedCurves.getByName("secp256k1");
    static final ECDomainParameters CURVE = new ECDomainParameters(
            CURVE_PARAMS.getCurve(), CURVE_PARAMS.getG(), CURVE_PARAMS.getN(), CURVE_PARAMS.getH());

    /**
     * Convert uncompressed public key to compress format
     * @param publicKey uncompressed public key biginteger
     * @return compressed public key string
     */
    @Deprecated
    public static String toCompressedPublicKey(BigInteger publicKey) {
        String hexStringPublicKey = Numeric.toHexStringNoPrefixZeroPadded(publicKey, 128);
        String publicKeyX = hexStringPublicKey.substring(0, 64);
        String pubKeyYPrefix = publicKey.testBit(0) ? "03" : "02";
        return pubKeyYPrefix + publicKeyX;
    }

    /**
     * Creates AccountKeyPublic(caver.tx.account.AccountKeyPublic) instance with converting uncompressed format
     * @param compressedPublicKey compressed public key
     * @return AccountKeyPublic(caver.tx.account.AccountKeyPublic)
     */
    @Deprecated
    public static AccountKeyPublic decompressKey(String compressedPublicKey) {
        boolean yBit = Numeric.cleanHexPrefix(compressedPublicKey).substring(0, 2).equals("03");
        BigInteger xBN = Numeric.toBigInt(compressedPublicKey.substring(2));
        X9IntegerConverter x9 = new X9IntegerConverter();
        byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve()));
        compEnc[0] = (byte)(yBit ? 0x03 : 0x02);
        ECPoint ecPoint = CURVE.getCurve().decodePoint(compEnc);
        return AccountKeyPublic.create(
                Numeric.toHexStringWithPrefixZeroPadded(ecPoint.getAffineXCoord().toBigInteger(), 64),
                Numeric.toHexStringWithPrefixZeroPadded(ecPoint.getAffineYCoord().toBigInteger(), 64)
        );
    }

    /**
     * Creates ECPoint instance using compressed public key
     * @param key public key
     * @return ECPoint
     */
    public static ECPoint getECPoint(String key) {
        if(isUncompressedPublicKey(key)) {
            key = Utils.compressPublicKey(key);
        }

        String noPrefixPublicKey = Numeric.cleanHexPrefix(key);
        boolean yBit = noPrefixPublicKey.startsWith("03");
        BigInteger xBN = Numeric.toBigInt(noPrefixPublicKey);
        X9IntegerConverter x9 = new X9IntegerConverter();
        byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve()));
        compEnc[0] = (byte)(yBit ? 0x03 : 0x02);
        ECPoint ecPoint = CURVE.getCurve().decodePoint(compEnc);
        return ecPoint;
    }

    /**
     * Creates ECPoint instance using ecc public key x,y coordinates
     * @param x x point
     * @param y y point
     * @return ECPoint
     */
    public static ECPoint getECPoint(String x, String y) {
        BigInteger bigIntegerX = Numeric.toBigInt(x);
        BigInteger bigIntegerY = Numeric.toBigInt(y);

        ECPoint ecPoint = CURVE.getCurve().createPoint(bigIntegerX, bigIntegerY);
        return ecPoint;
    }

    /**
     * Check if the X, Y coordinates included in the public key are valid.
     * @param compressedPubKey compressed public key
     * @return valid or not
     */
    public static boolean validateXYPoint(String compressedPubKey) {
        ECPoint point = getECPoint(compressedPubKey);
        return point.isValid();
    }

    /**
     * Check that given X, Y coordinates included in the public key.
     * @param x x point
     * @param y y point
     * @return valid or not
     */
    public static boolean validateXYPoint(String x, String y) {
        ECPoint point = getECPoint(x, y);
        return point.isValid();
    }

    /**
     * Check if the given key is in compressed format.
     * @param key public key
     * @return valid or not
     */
    public static boolean isCompressedPublicKey(String key) {
        String noPrefixKey = Numeric.cleanHexPrefix(key);

        if(noPrefixKey.length() == 66 && (noPrefixKey.startsWith("02") || noPrefixKey.startsWith("03"))) {
            if(!validateXYPoint(noPrefixKey)) {
                throw new RuntimeException("Invalid public key.");
            }
            return true;
        }
        return false;
    }

    /**
     * Check if the given key is in compressed format.
     * @param key public key
     * @return valid or not
     */
    public static boolean isUncompressedPublicKey(String key) {
        String noPrefixKey = Numeric.cleanHexPrefix(key);

        if(noPrefixKey.length() == 130) {
            if(!noPrefixKey.startsWith("04")) {
                throw new RuntimeException("Invalid public key.");
            }
            noPrefixKey = noPrefixKey.substring(2);
        }

        if(noPrefixKey.length() == 128) {
            String x = noPrefixKey.substring(0, 64);
            String y = noPrefixKey.substring(64);

            if(!validateXYPoint(x, y)) {
                throw new RuntimeException("Invalid public key.");
            }
            return true;
        }
        return false;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy