How to encrypt a string with another key? - java

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

Related

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 ?

How to create seed64 pattern for RFC6238?

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"

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

Java how to Modify IP Address that was input as a string

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

String outOfBoundsException while using charAt

I have the following code:
#SuppressWarnings("resource")
public void changeSkin(String name){
try {
URL uuidURL = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
String uuid = new Scanner(uuidURL.openStream(), "UTF-8").useDelimiter("\\A").next();
uuid = uuid.substring(7, 39);
System.out.println(uuid); // works
URL valueURL = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false");
String value = new Scanner(valueURL.openStream(), "UTF-8").useDelimiter("\\A").next();
value = value.replace('"', '!');
value = value.replaceAll("!value!:!", "*");
value = value.replaceAll("=!,", "+");
value = value.substring(value.charAt('*'), value.charAt('+')); // Gives an error outOfBounds: -13
String signature = new Scanner(valueURL.openStream(), "UTF-8").useDelimiter("\\A").next();
signature = signature.replaceAll("!signature!:!", "_");
signature = signature.replaceAll("=!}]}", "~");
signature = signature.substring(value.charAt('_'), value.charAt('~'));
System.out.println(signature);
System.out.println(value);
//profile.getProperties().put("textures", new Property(value, signature));
} catch (Exception e) {
e.printStackTrace();
}
}
While running it throws and outOfBoundsException: -13
But how can that throw a negative number?
Thanks for any help
Edit: Here is the website: https://sessionserver.mojang.com/session/minecraft/profile/e96ca9800c6c4a1588a2922a02ae1080?unsigned=false
I guess you are making some kind of minecraft bot or something ... but that's irrelevant.
You are using charAt incorrectly.
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#charAt(int)
What you are looking for is indexOf
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int)
You ask for the character position for '*' and THEN ask for the position '+'. The problem is that the plus is located BEFORE the star in the string, so it's returning a negative number.
To remedy, I would suggest breaking the substring into two lines:
value = value.substring(value.indexOf('*'));
value = value.substring(0, value.indexOf('+'));
Though it may seem irrelevant, breaking it into two lines breaks the string at the first instance of the * and then at the NEXT first instance of the +.

Categories