package com.oraclechain.eosio.crypto.ec; import com.oraclechain.eosio.crypto.digest.Ripemd160; import com.oraclechain.eosio.crypto.digest.Sha256; import com.oraclechain.eosio.crypto.util.Base58; import com.oraclechain.eosio.crypto.util.BitUtils; import com.oraclechain.eosio.dto.EosRefValue; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; import java.util.regex.PatternSyntaxException; public class EosEcUtil { public static final String PREFIX_K1 = "K1"; public static final String PREFIX_R1 = "R1"; // public static byte[] decodeEosCrypto(String base58Data, RefValue<CurveParam> curveParamRef, RefValue<Long> checksumRef ){ // // final byte[] retKeyData; // // final String typePrefix; // if ( base58Data.startsWith( EOS_PREFIX ) ) { // // if ( base58Data.startsWith( PREFIX_K1, EOS_PREFIX.length())) { // typePrefix = PREFIX_K1; // } // else // if ( base58Data.startsWith( PREFIX_R1, EOS_PREFIX.length())) { // typePrefix = PREFIX_R1; // } // else { // typePrefix = null; // } // // retKeyData = getBytesIfMatchedRipemd160( base58Data.substring( EOS_PREFIX.length() ), typePrefix, checksumRef); // } // else{ // typePrefix = null; // retKeyData = getBytesIfMatchedSha256( base58Data, checksumRef ); // } // // if ( curveParamRef != null) { // curveParamRef.data = EcTools.getCurveParam( PREFIX_R1.equals( typePrefix ) ? CurveParam.SECP256_R1 : CurveParam.SECP256_K1); // } // // return retKeyData; // } public static byte[] extractFromRipemd160( String base58Data ) { byte[] data= Base58.decode( base58Data ); if ( data[0] == data.length) { return Arrays.copyOfRange(data, 2, data.length ); } return null; } // public static byte[] getBytesIfMatchedRipemd160(String base58Data, String prefix, RefValue<Long> checksumRef ){ // byte[] prefixBytes = StringUtils.isEmpty(prefix) ? new byte[0] : prefix.getBytes(); // // byte[] data= Base58.decode( base58Data.substring( prefixBytes.length)); // // byte[] toHashData = new byte[data.length - 4 + prefixBytes.length]; // System.arraycopy( data, 0, toHashData, 0, data.length - 4); // key data // // System.arraycopy( prefixBytes, 0, toHashData, data.length - 4, prefixBytes.length); // // Ripemd160 ripemd160 = Ripemd160.from( toHashData); //byte[] data, int startOffset, int length // long checksumByCal = BitUtils.uint32ToLong( ripemd160.bytes(), 0); // long checksumFromData= BitUtils.uint32ToLong(data, data.length - 4 ); // if ( checksumByCal != checksumFromData ) { // throw new IllegalArgumentException("Invalid format, checksum mismatch"); // } // // if ( checksumRef != null ){ // checksumRef.data = checksumFromData; // } // // return Arrays.copyOfRange(data, 0, data.length - 4); // } public static byte[] getBytesIfMatchedRipemd160(String base58Data, String prefix, EosRefValue<Long> checksumRef ){ byte[] prefixBytes = StringUtils.isEmpty(prefix) ? new byte[0] : prefix.getBytes(); byte[] data= Base58.decode( base58Data ); byte[] toHashData = new byte[data.length - 4 + prefixBytes.length]; System.arraycopy( data, 0, toHashData, 0, data.length - 4); // key data System.arraycopy( prefixBytes, 0, toHashData, data.length - 4, prefixBytes.length); Ripemd160 ripemd160 = Ripemd160.from( toHashData); //byte[] data, int startOffset, int length long checksumByCal = BitUtils.uint32ToLong( ripemd160.bytes(), 0); long checksumFromData= BitUtils.uint32ToLong(data, data.length - 4 ); if ( checksumByCal != checksumFromData ) { throw new IllegalArgumentException("Invalid format, checksum mismatch"); } if ( checksumRef != null ){ checksumRef.data = checksumFromData; } return Arrays.copyOfRange(data, 0, data.length - 4); } public static byte[] getBytesIfMatchedSha256(String base58Data,EosRefValue<Long> checksumRef ){ byte[] data= Base58.decode( base58Data ); // offset 0은 제외, 뒤의 4바이트 제외하고, private key 를 뽑자 Sha256 checkOne = Sha256.from( data, 0, data.length - 4 ); Sha256 checkTwo = Sha256.from( checkOne.getBytes() ); if ( checkTwo.equalsFromOffset( data, data.length - 4, 4) || checkOne.equalsFromOffset( data, data.length - 4, 4) ){ if ( checksumRef != null ){ checksumRef.data = BitUtils.uint32ToLong( data, data.length - 4); } return Arrays.copyOfRange(data, 1, data.length - 4); } throw new IllegalArgumentException("Invalid format, checksum mismatch"); } // public static String encodeEosCrypto(byte[] data, CurveParam curveParam ) { // boolean isR1 = ( null != curveParam ) && curveParam.isType( CurveParam.SECP256_R1); // // byte[] toHashData = new byte[ data.length + (isR1 ? PREFIX_R1.length() : 0) ]; // System.arraycopy( data, 0, toHashData, 0, data.length); // if ( isR1 ) { // System.arraycopy( PREFIX_R1.getBytes(), 0, toHashData, data.length, PREFIX_R1.length()); // } // // byte[] result = new byte[ data.length + 4 ]; // // Ripemd160 ripemd160 = Ripemd160.from( toHashData); //byte[] data, int startOffset, int length // byte[] checksumBytes = ripemd160.bytes(); // // System.arraycopy( data, 0, result, 0, data.length); // copy source data // System.arraycopy( checksumBytes, 0, result, data.length, 4); // copy checksum data // // return EOS_PREFIX + ( isR1 ? PREFIX_R1 : "") + Base58.encode( result ); // } public static String encodeEosCrypto(String prefix, CurveParam curveParam, byte[] data ) { String typePart = ""; if ( curveParam != null ) { if ( curveParam.isType( CurveParam.SECP256_K1)) { typePart = PREFIX_K1; } else if ( curveParam.isType( CurveParam.SECP256_R1)){ typePart = PREFIX_R1; } } byte[] toHashData = new byte[ data.length + typePart.length() ]; System.arraycopy( data, 0, toHashData, 0, data.length); if ( typePart.length() > 0 ) { System.arraycopy( typePart.getBytes(), 0, toHashData, data.length, typePart.length()); } byte[] dataToEncodeBase58 = new byte[ data.length + 4 ]; Ripemd160 ripemd160 = Ripemd160.from( toHashData); byte[] checksumBytes = ripemd160.bytes(); System.arraycopy( data, 0, dataToEncodeBase58, 0, data.length); // copy source data System.arraycopy( checksumBytes, 0, dataToEncodeBase58, data.length, 4); // copy checksum data String result; if ( StringUtils.isEmpty( typePart)) { result = prefix; } else { result = prefix + EOS_CRYPTO_STR_SPLITTER + typePart + EOS_CRYPTO_STR_SPLITTER; } return result + Base58.encode( dataToEncodeBase58 ); } private static final String EOS_CRYPTO_STR_SPLITTER = "_"; public static String[] safeSplitEosCryptoString( String cryptoStr ) { if ( StringUtils.isEmpty( cryptoStr)) { return new String[]{ cryptoStr }; } try { return cryptoStr.split( EOS_CRYPTO_STR_SPLITTER ); } catch (PatternSyntaxException e){ e.printStackTrace(); return new String[]{ cryptoStr }; } } public static String concatEosCryptoStr( String... strData ) { String result=""; for ( int i = 0; i < strData.length; i++) { result += strData[i] + ( i < strData.length -1 ? EOS_CRYPTO_STR_SPLITTER : ""); } return result; } public static CurveParam getCurveParamFrom(String curveType ) { return EcTools.getCurveParam( PREFIX_R1.equals( curveType ) ? CurveParam.SECP256_R1 : CurveParam.SECP256_K1); } // public static EosCryptoProperty getEosCryptoProperty( String cryptoStr ) { // if ( StringUtils.isEmpty( cryptoStr)) { // return new EosCryptoProperty( cryptoStr ); // } // // String[] splitted = null; // try { // splitted = cryptoStr.split(EOS_CRYPTO_STR_SPLITTER); // // if ( splitted == null || splitted.length <= 1) { // return new EosCryptoProperty( cryptoStr ); // } // // return new EosCryptoProperty( splitted[0], null, splitted[1]); // } // } }