get bitcoin cash address from public key, using bitcoin-abc - public-key

hey i am using https://github.com/Bitcoin-ABC/bitcoin-abc and trying to get bch adress form ecdsa public key.
I have this compressed public key:
publickKey = "02c0fe3501b514b1b2136b4d923de0907314a7c92499fd29a0cb7cf9f731711a19"
This is its bitcoin address: "39n8cpkeHhJDzhTVkboagHMbr9WYSLv2Yk"
And according to https://cashaddr.bitcoincash.org/ this is its bitcoin-cash address: "bitcoincash:ppvt3t9zkp3flgvgunp0wpp6l9t9tc85kvhtg5zkvr"
i tried to get the bch address like this:
const auto netParams = bCreateChainParams(bCBaseChainParams::MAIN);
CTxDestination dst = CKeyID(uint160S(publickKey));
std::string encoded = EncodeCashAddr(dst, *netParams);
and i get different bitcoincash address (and not the one above)
i also tried:
std::vector<uint8_t> hashVector = std::vector<uint8_t>(uncompressKey(publickKey));
bCashAddrContent keyContent{PUBKEY_TYPE, hashVector};
string encoded = EncodeCashAddr("bitcoincash", keyContent);
when uncompressKey function uncompressing the ecdsa key and removes the headres from it.
i also tried with SCRIPT_TYPE instead of PUBKEY_TYPE, yet i dont get the right address....
i also cant find any example code
any idea?

i succeeded to get to the Compressed Bitcoin Cash Address:
CPubKey cPubKey = CPubKey(hash.begin(), hash.end());
auto dst = GetDestinationForKey(cPubKey, OutputType::LEGACY);
std::string encoded = EncodeCashAddr(dst, *netParams);
when "hash" is std::vector of the compressed public key (66 characters) and "encoded" is Bitcoin Cash Address Compressed
if someone knows how to get the regular address (uncompressed) please let me know

Related

yubihsm2 signatures are invalid when signing ETH transactions

I am trying to figure out how to get this yubihsm2 to work with signing eth transactions. I have been using the python lib and so far i have had some basic setup. Below is an abbreviation of what i have
web3_endpoint = ''
web3 = Web3(HTTPProvider(web3_endpoint))
hsm = YubiHsm.connect("http://localhost:12345")
session = hsm.create_session_derived(1, "password")
key = session.get_object(1,OBJECT.ASYMMETRIC_KEY)
#key = AsymmetricKey.generate(session, 1, "EC Key", 1, CAPABILITY.SIGN_ECDSA, ALGORITHM.EC_K256)
pub_key = key.get_public_key()
#raw_pub = pub_key.public_bytes(
# encoding=serialization.Encoding.DER,
# format=serialization.PublicFormat.SubjectPublicKeyInfo
# )
raw_pub = pub_key.public_bytes(
encoding=serialization.Encoding.X962,
format=serialization.PublicFormat.UncompressedPoint
)
print ("Public key (Uncompressed):\n",binascii.b2a_hex(raw_pub))
unindexPub = raw_pub[1:]
public_key_hash = Web3.keccak(unindexPub)
address_bytes = public_key_hash[-20:]
address = address_bytes.hex()
print(address)
Now so far i can consistently get the same public key and it looks correct. I then get the same public key each time. When i say correct, the formatting looks correct and is the correct number of bytes.
1). should i be using the commented out public key formatting or the uncompressed X962 encoding that i have above.
From there, this is where things get a bit weird
transaction = {
'to': Web3.toChecksumAddress('0x785AB1daE1b0Ee3f2412aCF55e4153A9517b07e1'),
'gas': 21000,
'gasPrice': Web3.toWei(5, 'gwei'),
'value': 1,
'nonce': 1,
'chainId': 4,
}
serializable_transaction = serializable_unsigned_transaction_from_dict(transaction)
transaction_hash = serializable_transaction.hash()
print(transaction_hash.hex())
# sign the transaction hash and calculate v value
signature = key.sign_ecdsa(transaction_hash,hashes.SHA3_256())
r, s = ecdsa.util.sigdecode_der(signature, ecdsa.SECP256k1.generator.order())
print("r: "+str(r)+"\ns: "+str(s))
v = 28
# encode the transaction along with the full signature and send it
encoded_transaction = encode_transaction(serializable_transaction, vrs=(v, r, s))
web3.eth.sendRawTransaction(encoded_transaction)
I am settings v to 28.. i also test it with 27.. I could use the correct amount with the chainid.. but it's not necessary right from the perspective of trying to get a valid signature (recoverable to get the same public key each time). Sometimes i am getting the error "invalid sender" and other times i am getting the error "insufficient gas." If i take the signature output and use a javascript lib to try to find the public key, each time i am getting a different public key. But i keep consistently generating the same public key from the yubihsm2 in this python app.
I have also commented out in sign_ecdsa the hashing function as i am passing in the data already hashed (in order to use keccak256).
Is there something i am missing? Why are these transactions not signing correctly for eth?
i am getting some of those serialization helpers from enter link description here
helper serialization functions
Thanks

AES encryption on mysql and node.js

I have struggle below question with days, and posted same question earlier and didn't get any positive feedback.
Im using mysql in build aes_encrypt method to encrypt new and existing data.
https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html
SET ##SESSION.block_encryption_mode = 'aes-256-ecb';
INSERT INTO test_aes_ecb ( column_one, column_two )
values ( aes_encrypt('text','key'), aes_encrypt('text', 'key'));
I used ecb ciper, so It no need to use iv for that. Issue is I can't decrypt it from node.js side.
Im using sequelize and tried to call data through model --> decrypt from node side.
I tried with below libraries,
"aes-ecb": "^1.3.15",
"aes256": "^1.1.0",
"crypto-js": "^4.1.1",
"mysql-aes": "0.0.1",
Below are code snippets from sequelize call
async function testmysqlAESModel () {
const users = await test.findAll();
console.log('users', users[0].column_one);
var decrypt = AES.decrypt( users[0].column_one, 'key' );
}
Its returning buffer data and couldn't decrypt from node side, Can someone provide proper example for that? Im struggling for days.
EDIT
Inserted record to mysql as below query.
SET ##SESSION.block_encryption_mode = 'aes-256-ecb';
INSERT INTO test_aes_ecb ( id, column_one, column_two )
VALUES (1, 2,AES_ENCRYPT('test',UNHEX('gVkYp3s6v9y$B&E)H#McQeThWmZq4t7w')));
In nodejs called like this,
testmysqlAESModel();
async function testmysqlAESModel () {
const users = await test.findAll();
console.log('users', users[0].column_one);
var decipher = crypto.createDecipheriv(algorithm, Buffer.from("gVkYp3s6v9y$B&E)H#McQeThWmZq4t7w", "hex"), "");
var encrypted = Buffer.from(users[0].column_one); // Note that this is what is stored inside your database, so that corresponds to users[0].column_one
var decrypted = decipher.update(encrypted, 'binary', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
}
Im getting below error,
I used below link to create 256bit key.
https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx
Still couldn't fix, can you provide sample project or any kind of supporting code snippet for that ?
There are multiple issues here:
Ensure that your key has the correct length. AES is specified for certain key length (i.e. 128, 196 and 256 bit). if you use any other key length, then your key will be padded (zero extended) or truncated by the crypto library. This is a non-standard process, and different implementations will do this differently. To avoid this, use a key in the correct length and store it has hex instead of ascii (to avoid charset issues)
Potential issues regarding password to key inference. Some AES implementations use methods to infer keys from passwords/passphrases. Since you are using raw keys in MySQL, you do not want to infer anything but want to use raw keys in NodeJS as well. This means that if you are using the native crypto module, that you want to use createDecipheriv instead of createDecipher.
Caution: The AES mode you are using (ECB) is inherently insecure, because equal input leads to equal output. There are ways around that using other AES modes, such as CBC or GCM. You have been warned.
Example:
MySQL SELECT AES_ENCRYPT('text',UNHEX('F3229A0B371ED2D9441B830D21A390C3')) as test; returns the buffer [145,108,16,83,247,49,165,147,71,115,72,63,152,29,218,246];
Decoding this in Node could look like this:
var crypto = require('crypto');
var algorithm = 'aes-128-ecb';
var decipher = crypto.createDecipheriv(algorithm, Buffer.from("F3229A0B371ED2D9441B830D21A390C3", "hex"), "");
var encrypted = Buffer.from([145,108,16,83,247,49,165,147,71,115,72,63,152,29,218,246]); // Note that this is what is stored inside your database, so that corresponds to users[0].column_one
var decrypted = decipher.update(encrypted, 'binary', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
This prints text again.
Note that F3229A0B371ED2D9441B830D21A390C3 is the key in this example, you would obviously have to create your own. Just ensure that your key has the same length as the example, and is a valid hex string.

How to properly pass uint256 numbers to smart contract from frontend?

I have some math on frontend, which works good, but when math calculate big Numbers like this 1.1350120633522164e+23
I get error
Unhandled Rejection (Error): invalid number value
(arg="minDestinationAmount", coderType="uint256",
value="1.1350120633522164e+23", version=4.0.44)
I used BN
const minDestBN = new BigNumber(input)
const minDestinationAmount = minDestBN.multipliedBy(99).dividedBy(100)
res minDestinationAmoun = 1.1350120633522164e+23
How to convert such numbers 1.1350120633522164e+23 to uint256 on frontend side ?
This help me
BigNumber.config({ EXPONENTIAL_AT: 1e+9 })
let minDestinationAmount = minDestBN.multipliedBy(99).dividedBy(100)
minDestinationAmount = String(minDestinationAmount)
But would be great to hear best practice

Kernel32.dll - DeviceIOControl returns false while trying to get String descriptor in Win 10

I am currently using the DeviceIOControl API from kernel32.dll to get the String Descriptors of the list of connected USB devices.
public static String GetStringDescriptor(IntPtr deviceHandle, Int32 ConnectionIndex, Byte DescriptorIndex, UInt16 LanguageID)
{
USB_DESCRIPTOR_REQUEST Buffer = new USB_DESCRIPTOR_REQUEST();
Buffer.ConnectionIndex = ConnectionIndex;
Buffer.SetupPacket.wValue = (UInt16)((USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex);
Buffer.SetupPacket.wIndex = LanguageID;
Buffer.SetupPacket.wLength = MAXIMUM_USB_STRING_LENGTH;
Int32 nBytesReturned;
Boolean Status = DeviceIoControl(deviceHandle,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);
if (Status)
return Buffer.Data.bString;
else
return null;
}
We use this function to get the descriptor details such as Language ID, Serial number, Manufacturer and Product String. Only while requesting the Serial Number, the Status returned is TRUE and we get the expected values. But the status returns false for Language id, manufacturer and Product string.
I checked the error status returned by the DeviceIoControl using:
int error = Marshal.GetLastWin32Error();
It returns 31 as the error code which means that the Device is not working properly/ the driver for the device is not properly installed.
I tried all the obvious solutions like reinstalling the driver for the device and restarting the PC etc., but none seems to work. I am sure there are no issues in the device or the code because it works flawlessly in windows 7 PCs. Also, since I am able to get the serial number, I think the device handle is also proper.
I am not able to proceed with any further debugging. Is there some update to the DeviceIoControl function in Windows 10? Or is the way to get the languageID, manufacturer and Product String changed in Windows 10?
Most probably the device you are trying to get string descriptors from is in low power state. Check its current power state first, and if it differs from "PowerDeviceD0" - string descriptors may not be obtained (depending on device, actually, and actual power state level D1, D2, D3). This could be the cause of error code 31 from DeviceIOControl().
Try to wake the device first or get some stored strings with SetupAPI.

I want to find a hash function to generate a hash with a given length

Just like the title, I want to find a hash function to generate a hash with a given length. From the Internet I found one solution is I can use the SHAKE256 technique. But I cannot find some java code to use the SHAKE256. Anyone can provide me some sample java code so that I can use it in my code?
I typed java shake256 into Google and found this solution as the 2nd result: https://github.com/aelstad/keccakj. It is a Java library called "keccakj" that is able to compute shake256 hashes, among others.
For shake256, to generate a hash of an arbitrary bit length d and d < 256, you can just trim the result of SHAKEDigest from bouncycastle.
public static byte[] hash(byte[] src, int byteLength){
//import org.bouncycastle.crypto.digests.SHAKEDigest;
Assert.assertTrue("do not support result length more than 32", byteLength<=32);
SHAKEDigest d = new SHAKEDigest(256);
byte[]checksumByte = new byte[32];
d.update(src,0,src.length);
d.doFinal(checksumByte,0);
return Arrays.copyOf(checksumByte,byteLength);
}