I used SCALE Codec for java offline address generation. but I see that generated address and polkadot.js generated address are not alike.
I use bitcoinj 's MnemonicCode generation mnemonic, and I toseed the mnemonic get seed;
this is my code;
public void createAddress() throws Exception {
System.out.println("Generate a new Root Key + derive a `demo` address from that key");
int number = 0;
byte[] initialEntropy = new byte[128 / 8];
SecureRandomUtils.secureRandom().nextBytes(initialEntropy);
String mnemonic = "devote fatigue dice clock lock cross creek neutral minute achieve betray curve";
String[] mm = mnemonic.split(" ");
List<String> strings = Arrays.asList(mm.clone());
System.out.println(mnemonic);
String n = Utils.SPACE_JOINER.join(strings);
System.out.println(n);
byte[] seed = toSeed(strings, "");
String s = Hex.encodeHexString(seed);
System.out.println(s);
Schnorrkel instance = Schnorrkel.getInstance();
Schnorrkel.KeyPair rootKey = instance.generateKeyPairFromSeed(seed);
System.out.println(" Root Key: " + Hex.encodeHexString(rootKey.getSecretKey()));
Schnorrkel.KeyPair key = instance.deriveKeyPair(rootKey, Schnorrkel.ChainCode.from("".getBytes()));
Address address = new Address(SS58Type.Network.LIVE, key.getPublicKey());
System.out.println(" Address: " + address);
System.out.println("Public Key: " + Hex.encodeHexString(key.getPublicKey()));
System.out.println("Secret Key: " + Hex.encodeHexString(key.getSecretKey()));
}
public static byte[] toSeed(List<String> words, String passphrase) {
checkNotNull(passphrase, "A null passphrase is not allowed.");
// To create binary seed from mnemonic, we use PBKDF2 function
// with mnemonic sentence (in UTF-8) used as a password and
// string "mnemonic" + passphrase (again in UTF-8) used as a
// salt. Iteration count is set to 4096 and HMAC-SHA512 is
// used as a pseudo-random function. Desired length of the
// derived key is 512 bits (= 64 bytes).
//
String pass = Utils.SPACE_JOINER.join(words);
String salt = "mnemonic" + passphrase;
final Stopwatch watch = Stopwatch.createStarted();
byte[] seed = PBKDF2SHA512.derive(pass, salt, 2048, 32);
watch.stop();
System.out.println("PBKDF2 took {}" + watch);
return seed;
}
polkadot.js generated address is "12EgmkT6NHjTjtwcvfBFu1dkPEN9TLFo3ftA4L2ZcmkCfQCp";
i use my code generated address is "12YTJRjPRsw34wBp2Ewfr9oBP9w47RpKKw4CPZF2zaCga1Hk"
how do I generate similar polkadot.js' address ?
Related
I have a string than I want to encrypt to send it over an insecure channel.
I want to:
Convert to int my-val & my-private-key. Then, multiply both. Send it. When receiving it, divide by my-private-key converted as int and get my-val.
I tried to used Integer.parseInt and Integer.toString as suggested here. It seems to work with System.out.println(Integer.parseInt("Kona", 27)); (as Java's documentation said)
So I made this:
int base = 27;
String key = "some key";
String cmd = "some val";
int based = Integer.parseInt(cmd, base);
System.out.println("Based: " + based);
int crypted = based * Integer.parseInt(key, base);
System.out.println("Crypted: " + crypted);
// here use un-secure channel to send/receive
int received = crypted;
int back = received / Integer.parseInt(key, base);
System.out.println("Get back: " + back);
System.out.println("Final result: " + Integer.toString(back, base));
But I get Exception in thread "main" java.lang.NumberFormatException: For input string: "some val" at the 4st line.
I tried with base 10, 16, 27, 32. Even if I understand why 10 & 16 doesn't work, why 27 & 32 don't ? How can I fix it ?
Based on below wikipedia link of numeral system, Java will check each character of your input string against the range of radix parameter and if its not in range than it will throw exception.
Visit https://en.wikipedia.org/wiki/List_of_numeral_systems,
Apart from that, Below is explanation from geeksforgeek site.
The string is null or of zero-length
The value represented by the string is not a value of type int
Specifically for the parseInt(String s, int radix) variant of the function:
The second argument radix is either smaller than Character.MIN_RADIX or larger than Character.MAX_RADIX
*
Each character of input string has min and max radix parameter.
Any character of the string is not a digit of the specified radix, except that the first character may be a minus sign ‘-‘ (‘\u002D’) or plus sign ‘+’ (‘\u002B’) provided that the string is longer than length 1
Custom logic for conversion
String name = "some val";
long key = 0;
for (int i = 0;i<name.length();i++)
key+= (name.charAt(i) - 'a'+1 ) * Math.pow(26,name.length() - i - 1 );
System.out.println(key);
Above code is taken Converting name to a key using radix-26
I was looking to encrypt with another string. I get the idea to multiply both, and so convert them into int. But, it seems to have informations lost with operation.
So, I searched for another way, and I found this one:
private static final String ALGORITHM = "AES";
private static final Key MY_KEY = new SecretKeySpec("16-char priv key".getBytes(), ALGORITHM);
private Cipher getCipher(int mode) throws Exception {
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(mode, MY_KEY);
return c;
}
public String encrypt(String valueToEnc) throws Exception {
return Base64.getEncoder().encodeToString(getCipher(Cipher.ENCRYPT_MODE).doFinal(valueToEnc.getBytes()));
}
public String decrypt(String encryptedValue) throws Exception {
return new String(getCipher(Cipher.DECRYPT_MODE).doFinal(Base64.getDecoder().decode(encryptedValue)));
}
How it works ? It encrypt and decrypt with a key. This key should be a 16-chars one. Also, to make it easier to show/send/receive, it's converted into base 64.
Example of how to use:
String myVal = "some val";
String encrypt = encrypt(myVal);
System.out.println("Encrypt: " + encrypt);
String decrypt = decrypt(encrypt);
System.out.println("Decrypt: " + decrypt);
Output:
Encrypt: ERJZ7ZOJcNpQEAvrb6wPOA==
Decrypt: some val
I'm following the RFC DOCUMENTATION to implement the algorithm in Java. Using the same test token shared value 1234567890 Appendix B and I got the same results.
But I don't understand the seed32, seed64 pattern, in the example, we have patterns like this :
// Seed for HMAC-SHA1 - 20 bytes
String seed = "3132333435363738393031323334353637383930";
// Seed for HMAC-SHA256 - 32 bytes
String seed32 = "3132333435363738393031323334353637383930" +
"313233343536373839303132";
// Seed for HMAC-SHA512 - 64 bytes
String seed64 = "3132333435363738393031323334353637383930" +
"3132333435363738393031323334353637383930" +
"3132333435363738393031323334353637383930" +
"31323334";
And:
3132333435363738393031323334353637383930
Is the HEX value of ASCII string :
12345678901234567890
Let's suppose I have this ASCII string :
aaa.bbbbbbbb.ccc#gmail.comAAAABBBBBCCCCCCDDD
The equivalent HEX is :
6161612e62626262626262622e63636340676d61696c2e636f6d414141414242424242434343434343444444
So how do I get the seed, seed 32, seed 64 from this HEX result?
string seed="what's the seed value"
string seed32="what's the seed32 value"
string seed64="what's the seed64 value"
Edit:
Resolved the issue with below code:
String tokenId="0x1800000000001289000000000000000000000000000000000000000000000000";
BigInteger token1;
if (tokenId.startsWith("0x")){
token1=new BigInteger(tokenId.substring(2),16);
I have a long String that I need to assign as BigInteger and pass it to another method of Web3j library. However, I keep receiving number format exception. Any help on this ?
Below is the method throwing exception:
public void getBalance1155(String walletAddress) throws ExecutionException, InterruptedException {
//define constant values
Web3j web3j=Web3j.build(new HttpService("https://mainnet.infura.io/v3/<apiKey>>"));
String contractAddress = "0xfaaFDc07907ff5120a76b34b731b278c38d6043C";
BigInteger tokenId=new BigInteger("0x1800000000001289000000000000000000000000000000000000000000000000",16);
NoOpProcessor processor = new NoOpProcessor(web3j);
Credentials credentials = Credentials.create("privatekey");
TransactionManager txManager = new FastRawTransactionManager(web3j, credentials, processor);
//Query Blockchain to get balance of WALLETADDRESS from Contract for given TokenID
ERC1155 token = ERC1155.load(contractAddress, web3j, txManager, DefaultGasProvider.GAS_PRICE, DefaultGasProvider.GAS_LIMIT);
RemoteCall<BigInteger> sendCall = token.balanceOf(walletAddress, tokenId);
BigInteger balance=sendCall.sendAsync().get();
log.info("balance >>>>>> " +balance);
}
Here's the Exception:
java.lang.NumberFormatException: For input string: "0x1800000000001289000000000000000000000000000000000000000000000000"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Long.parseLong(Long.java:692)
at java.base/java.lang.Long.parseLong(Long.java:817)
Drop the extraneous 0x from the string.
The documentation for BigInteger's constructor says
The String representation consists of an optional minus or plus sign followed by a sequence of one or more digits in the specified radix.
[...] The String may not contain any extraneous characters
No mention of prefixes like 0x (or 0 for octal).
You need to remove the 0x, you can retrieve the hexa value by using toString(16) on your BigInteger
BigInteger tokenId=new BigInteger("1800000000001289000000000000000000000000000000000000000000000000",16);
System.out.println("tokenId.toString(16) = " + tokenId.toString(16));
System.out.println("tokenId.toString(10) = " + tokenId.toString(10));
String originalString = "0x" + tokenId.toString(16);
System.out.println("originalString = " + originalString);
outputs:
tokenId.toString(16) = 1800000000001289000000000000000000000000000000000000000000000000
tokenId.toString(10) = 10855508365998423105807514254364715762064874182780947284375732482585619595264
originalString = 0x1800000000001289000000000000000000000000000000000000000000000000
As you are already using web3j you can use Numeric.decodeQuantity("0x1800000000001289000000000000000000000000000000000000000000000000") this decode the hexideimal into a BigInteger
I have a program that will take a LAN IP provided, I then need to be able to modify just the last octet of the IP's, the first 3 will remain the same based on what was input in the LAN IP Text Field.
For example:
User enter 192.168.1.97 as the LAN IP I need to be able to manipulate the last octet "97", how would I go about doing that so I can have another variable or string that would have say 192.168.1.100 or whatever else i want to set in the last octet.
String ip = "192.168.1.97";
// cut the last octet from ip (if you want to keep the . at the end, add 1 to the second parameter
String firstThreeOctets = ip.substring(0, ip.lastIndexOf(".")); // 192.168.1
String lastOctet = ip.substring(ip.lastIndexOf(".") + 1); // 97
Then, if you want to set the last octet to 100, simply do:
String newIp = firstThreeOctet + ".100"; // 192.168.1.100
You can use these methods
public static byte getLastOctet(String ip) {
String octet = ip.substring (ip.lastIndexOf('.') + 1);
return Byte.parseByte(octet);
}
public static String setLastOctet(String ip, byte octet) {
return ip.substring(0, ip.lastIndexOf ('.') + 1) + octet;
}
Replace the number at the end of the input.
String ipAddress = "192.168.1.97";
String newIpAddress = ipAddress.replaceFirst("\\d+$", "100")
You can do this with the IPAddress Java library as follows. Doing it this way validates the input string and octet value. Disclaimer: I am the project manager.
static IPv4Address change(String str, int lastOctet) {
IPv4Address addr = new IPAddressString(str).getAddress().toIPv4();
IPv4AddressSegment segs[] = addr.getSegments();
segs[segs.length - 1] = new IPv4AddressSegment(lastOctet);
return new IPv4Address(segs);
}
IPv4Address next = change("192.168.1.97", 100);
System.out.println(next);
Output:
192.168.1.100
I'm attempting to implement Diffie-Hellman key exchange. I am a little confused with how to use the secret key once generated.
As seen in the output, the 2 secret keys are generated using the same prime & base as normal in the key exchange, and trade public keys when generating the secret keys, however they are not outputting the same value as I expected.
I'm getting very confused with how to implement this encryption method and would be very grateful for some direction. My overall aim for this is to implement an encrypted SMS Android application.
(The screenshot was unable to capture the entire length of a & b's base & prime)
AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH");
paramGen.init(512); // number of bits
AlgorithmParameters params = paramGen.generateParameters();
DHParameterSpec dhSpec = (DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
BigInteger p512 = dhSpec.getP();
BigInteger g512 = dhSpec.getG();
//A
KeyPairGenerator akpg = KeyPairGenerator.getInstance("DiffieHellman");
DHParameterSpec param = new DHParameterSpec(p512, g512);
System.out.println("Prime: " + p512);
System.out.println("Base: " + g512);
akpg.initialize(param);
KeyPair kp = akpg.generateKeyPair();
//B
KeyPairGenerator bkpg = KeyPairGenerator.getInstance("DiffieHellman");
DHParameterSpec param2 = new DHParameterSpec(p512, g512);
System.out.println("Prime: " + p512);
System.out.println("Base: " + g512);
bkpg.initialize(param2);
KeyPair kp2 = bkpg.generateKeyPair();
KeyAgreement aKeyAgree = KeyAgreement.getInstance("DiffieHellman");
KeyAgreement bKeyAgree = KeyAgreement.getInstance("DiffieHellman");
aKeyAgree.init(kp.getPrivate());
bKeyAgree.init(kp2.getPrivate());
aKeyAgree.doPhase(kp2.getPublic(), true);
bKeyAgree.doPhase(kp.getPublic(), true);
//System.out.println("Alice Secret Key: " + aKeyAgree.generateSecret());
//System.out.println("Bob's Secret Key: " + bKeyAgree.generateSecret());
MessageDigest hash = MessageDigest.getInstance("SHA-256");
byte[] ASharedSecret = hash.digest(aKeyAgree.generateSecret());
byte[] BSharedSecret = hash.digest(bKeyAgree.generateSecret());
System.out.println("Alice's Shared Secret: " + ASharedSecret.toString());
System.out.println("Bob's Shared Secret: " + BSharedSecret.toString());
byte[].toString() doesn't print the contents. Try Arrays.toString().