How to create seed64 pattern for RFC6238? - java

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"

Related

How to encrypt a string with another key?

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

Java offline generation polkadot address

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 ?

BigInteger throws numberFormatException

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

Strange StringIndexOutofBoundsException caused when converting hex string to binary

I'm not sure what is causing this exception, and the stack trace isn't being helpful as it states it was caused by an unknown source.
The method below takes two hexadecimal strings, one representing an opcode and one representing an operand, and converts them to binary before concatenating them and adding them to an arraylist. Simple enough. In order to ensure each binary string includes the full 8 bits I'm using a small utility method called hexToBinary, for some reason, when I attempt to use this method to convert my hexadecimal strings it causes the exception.
The opcode and operands, which are taken from the asmLine objects give this input below:
A9 10
90 C6
0A 00
11 FF
38 00
7D FF
81 FF
A1 09
AA 00
20 11
58 00
6C 09
FE 10
All of the above hexadecimal values should be converted to binary. But this is not happening. The strange thing is that when I explicitly state the hexadecimal value to be converted by the utility method, as I do with the line String beginBinary = Utils.hexToBinary("FA"); works completely normally. I just can't understand why this isn't working when I'm using the values pulled from the asmLine objects.
public void constructBinaryOutput()
{
ArrayList<String> binaryOut = new ArrayList<String>();
String beginBinary = Utils.hexToBinary("FA"); //This works normally
String endBinary = Utils.hexToBinary("FF"); //This works normally
String twoByteString = beginBinary.concat(" " + beginBinary);
binaryOut.add(twoByteString);
for(AssemblyLine asmLine : lineObjects)
{
String opcodeHex = asmLine.getOpcodeHEX();
String operandHex = asmLine.getOperandHEX();
System.out.println("Hex opcode/operand: " + opcodeHex + " " + operandHex);
String opcodeBinary = Utils.hexToBinary(opcodeHex); //This causes an exception
String operandBinary = Utils.hexToBinary(operandHex);
System.out.println("Hex opcode " + asmLine.getOpcodeHEX() + " converted into binary " + opcodeBinary);
System.out.println("Hex operand " + asmLine.getOperandHEX() + " converted into binary " + operandBinary);
twoByteString = opcodeBinary.concat(" " + operandBinary);
System.out.println("2 Byte instruction: " + twoByteString);
binaryOut.add(twoByteString);
}
}
Utility method hexToBinary
public static String hexToBinary(String hex)
{
String bin = Integer.toBinaryString(Integer.parseInt(hex,16));
int length = bin.length();
return length == 8 ? bin : "00000000".substring(length - 8) + bin;
}
Just a simple mistake in your util function. It should be:
public static String hexToBinary(String hex) {
String bin = Integer.toBinaryString(Integer.parseInt(hex, 16));
int length = bin.length();
return length == 8 ? bin : "00000000".substring(length) + bin;
}
notice the substring.
HTH,
Gal

Extract specific values or substrings from long string using regex in java

I have a long string containing different values/strings i want to extract.
String info = "ABHom=1.00;AC=2;AF=1.00;AN=2;DP=24;Dels=0.00;FS=0.000;
HaplotypeScore=0.9947;MLEAC=2;MLEAF=1.00;MQ=53.03;MQ0=0;QD=32.49;
VQSLOD=2.70; culprit=FS";
Matcher matcher = Pattern.compile("[A][B][h][o][m][=]([0-9]+\\.[0-9]+)").matcher(info);
if (matcher.find()) {
String someNumberStr = matcher.group(1);
ABhom = Double.parseDouble(someNumberStr);
Matcher matcher = Pattern.compile("[M][L][E][A][C][=]/([0-9]+)").matcher(info);
if (matcher.find()) {
String someNumberStr = matcher.group(1);
MLEAC = Integer.parseInt(someNumberStr);
I'am new to regex. Is there any smarter way to extract the numbers/strings after the equals sign ?
I'am thankful for any suggestions!
I think what you want to do is to turn your String into a HashMap<String,String>.
First, you'll need to split your string around semicolons. Then, iterate the array that you get, splitting each entry around the equals sign, and adding the result to the HashMap.
I suggest you read about the split method of the String class for how to do this, and also read about the HashMap class. Look at http://docs.oracle.com/javase/7/docs/api/java/lang/String.html and http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html and post again if you need more help.
You can do like this
String[] split = info.split(";");
for (String string : split) {
String[] split2 = string.trim().split("=");
System.out.println(split2[0] +" :" +split2[1]);
}
You can store them in HashMap as follows:
String[] parts = info.split(";");
Map<String, String> hashMap = new HashMap<String, String>();
for (String s : parts) {
String[] keyVal = s.trim().split("=");
hashMap.put(keyVal[0], keyVal[1]);
}
and later on you may use hashMap object to get it's values.
String info = "ABHom=1.00;AC=2;AF=1.00;AN=2;DP=24;Dels=0.00;FS=0.000;"
+ " HaplotypeScore=0.9947;MLEAC=2;MLEAF=1.00;MQ=53.03;MQ0=0;QD=32.49;"
+ "VQSLOD=2.70; culprit=FS";
Pattern pattern = Pattern.compile("(\\w+)=(\\d+(.\\d+)?)");
Matcher matcher = pattern.matcher(info);
while (matcher.find()) {
System.out.println("key: "+matcher.group(1) +" value: "+matcher.group(2));
}
output :
key: ABHom value: 1.00
key: AC value: 2
key: AF value: 1.00
key: AN value: 2
key: DP value: 24
key: Dels value: 0.00
key: FS value: 0.000
key: HaplotypeScore value: 0.9947
key: MLEAC value: 2
key: MLEAF value: 1.00
key: MQ value: 53.03
key: MQ0 value: 0
key: QD value: 32.49
key: VQSLOD value: 2.70
explanation :
\\w mean any character include _ \\w+ means array of characters
\\d mean any digit \\d+ means array of digits
? Matches the preceding element zero or one time. For example, ab?c matches only "ac" or "abc".
you said that i want to extract string and numbers , because of this the code above can not extract culprit=FS but if you want to extract all pair you should use this code :
Pattern pattern = Pattern.compile("(\\w+)=([^;]+)");
Matcher matcher = pattern.matcher(info);
while (matcher.find()) {
System.out.println("key: "+matcher.group(1) +" value: "+matcher.group(2));
}
output :
key: ABHom value: 1.00
key: AC value: 2
key: AF value: 1.00
key: AN value: 2
key: DP value: 24
key: Dels value: 0.00
key: FS value: 0.000
key: HaplotypeScore value: 0.9947
key: MLEAC value: 2
key: MLEAF value: 1.00
key: MQ value: 53.03
key: MQ0 value: 0
key: QD value: 32.49
key: VQSLOD value: 2.70
key: culprit value: FS
I don't think regex is a good idea. Try info.split(";")[0].split("=")[1] with some extra boundary check.

Categories