Has anyone here successfully generated the Walmart.io API signature key?
I have tried to wrap my head around the java example but I am not having any luck of it as I have no Java experience.
I saw that there is a Python example here on StackOverFlow which would be interesting too, but it didn't work for me.
The result I'm getting with Walmart Java code:
consumerId: 36e010ef-0026-4713-9365-231323116afd
intimestamp: 1665872674888
Signature: null
My code:
package com.walmart.platform.common;
import java.io.ObjectStreamException;
import java.security.KeyRep;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.commons.codec.binary.Base64;
public class SignatureGenerator {
public static void main(String[] args) {
SignatureGenerator generator = new SignatureGenerator();
String consumerId = "36e010ef-0026-4713-9365-231323116afd";
String priviateKeyVersion = "2";
String key = "jUiewb1+QbHl7ls+LoBO...O4j2NVjC2If4Z/r5FrykDVcO+nxb8G95X+zl";
long intimestamp = System.currentTimeMillis();
System.out.println("consumerId: " + consumerId);
System.out.println("intimestamp: " + intimestamp);
Map<String, String> map = new HashMap<>();
map.put("WM_CONSUMER.ID", consumerId);
map.put("WM_CONSUMER.INTIMESTAMP", Long.toString(intimestamp));
map.put("WM_SEC.KEY_VERSION", priviateKeyVersion);
String[] array = canonicalize(map);
String data = null;
try {
data = generator.generateSignature(key, array[1]);
} catch(Exception e) { }
System.out.println("Signature: " + data);
}
public String generateSignature(String key, String stringToSign) throws Exception {
Signature signatureInstance = Signature.getInstance("SHA256WithRSA");
ServiceKeyRep keyRep = new ServiceKeyRep(KeyRep.Type.PRIVATE, "RSA", "PKCS#8", Base64.decodeBase64(key));
PrivateKey resolvedPrivateKey = (PrivateKey) keyRep.readResolve();
signatureInstance.initSign(resolvedPrivateKey);
byte[] bytesToSign = stringToSign.getBytes("UTF-8");
signatureInstance.update(bytesToSign);
byte[] signatureBytes = signatureInstance.sign();
String signatureString = Base64.encodeBase64String(signatureBytes);
return signatureString;
}
protected static String[] canonicalize(Map<String, String> headersToSign) {
StringBuffer canonicalizedStrBuffer=new StringBuffer();
StringBuffer parameterNamesBuffer=new StringBuffer();
Set<String> keySet=headersToSign.keySet();
// Create sorted key set to enforce order on the key names
SortedSet<String> sortedKeySet=new TreeSet<String>(keySet);
for (String key :sortedKeySet) {
Object val=headersToSign.get(key);
parameterNamesBuffer.append(key.trim()).append(";");
canonicalizedStrBuffer.append(val.toString().trim()).append("\n");
}
return new String[] {parameterNamesBuffer.toString(), canonicalizedStrBuffer.toString()};
}
class ServiceKeyRep extends KeyRep {
private static final long serialVersionUID = -7213340660431987616L;
public ServiceKeyRep(Type type, String algorithm, String format, byte[] encoded) {
super(type, algorithm, format, encoded);
}
protected Object readResolve() throws ObjectStreamException {
return super.readResolve();
}
}
}
Looks like private key you are using is not valid. Could you please regenerate public/private key pair and input valid private key. It will generate signature
Please follow the instructions listed here
https://walmart.io/docs/affiliate/quick-start-guide
https://walmart.io/key-tutorial
Regards,
Firdos
IO Support
Related
I have created a class that allows the user to create and store compounds into a Hash Map and now I want to create another class that allows me to take the values stored in that Hash Map and save them into a text file. I'm not sure if this is needed, but here is the code for the first class that I created containing the Hash Map:
package abi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class ChemicalComp {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Map<String, String> data = new HashMap<String, String>();
while(true){
String readinput=br.readLine();
if(readinput.equals(""))
break;
String input = readinput.replaceAll("\"", "");
String array[]=input.split(", ");
String compound=array[0];
String formula="";
for(int i=1;i<array.length;i++){
if(!array[i].equals("1")){
formula+=array[i];
}
}
data.put(compound, formula);
}
if(!data.isEmpty()) {
#SuppressWarnings("rawtypes")
Iterator it = data.entrySet().iterator();
while(it.hasNext()) {
#SuppressWarnings("rawtypes")
Map.Entry obj = (Entry) it.next();
System.out.println(obj.getKey()+":"+obj.getValue());
}
}
}
}
I'm not too familiar with text files, but I have done some research and this is what I've gotten so far. I know its pretty basic and that I will probably need some type of getter method, but I'm not sure where to incorporate it into what I have. Here is what I have for the class containing the text file:
package abi;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
public class CompoundManager {
private String path;
private boolean append_to_file = false;
public CompoundManager(String file_path) {
path = file_path;
}
public CompoundManager(String file_path, boolean append_value){
path = file_path;
append_to_file = append_value;
}
public void WriteToFile (String textLine) throws IOException{
FileWriter Compounds = new FileWriter(path, append_to_file);
PrintWriter print_line = new PrintWriter (Compounds);
print_line.printf("%s" + "%n", textLine);
print_line.close();
}
}
I can't understand what your program does but you can use a buffered writer for it.
Just create a try-catch block and wrap a filewriter in a bufferedwriter like this :
try (BufferedWriter br = new BufferedWriter(new FileWriter(new File("filename.txt"))))
{
for (Map.Entry<Integer, String> entry : map.entrySet()) {
int key = entry.getKey();
String value = entry.getValue();
br.write(key + ": " + value);
br.newLine();
}
} catch (Exception e) {
printStackTrace();
}
This question already has an answer here:
Why Objects.hash() returns different values for the same input?
(1 answer)
Closed 3 years ago.
Given the following class:
package software.visionary.identifr;
import software.visionary.identifr.api.Authenticatable;
import software.visionary.identifr.api.Credentials;
import javax.crypto.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Objects;
public final class PasswordCredentials implements Credentials {
private final Authenticatable owner;
private final byte[] value;
private final SecretKey key;
public PasswordCredentials(final Authenticatable human, final String password) {
if (Objects.requireNonNull(password).trim().isEmpty()) {
throw new IllegalArgumentException("Invalid password");
}
this.owner = Objects.requireNonNull(human);
this.key = asSecretKey(password);
this.value = this.key.getEncoded();
}
private SecretKey asSecretKey(final String password) {
try {
final PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
final SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndTripleDES");
return secretKeyFactory.generateSecret(pbeKeySpec);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new RuntimeException(e);
}
}
#Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) {
return false;
}
final PasswordCredentials that = (PasswordCredentials) o;
return owner.equals(that.owner) &&
Arrays.equals(value, that.value);
}
#Override
public int hashCode() {
return Objects.hash(owner, value);
}
}
And the following tests:
package software.visionary.identifr;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import software.visionary.Randomizr;
import software.visionary.identifr.api.Authenticatable;
import software.visionary.identifr.api.Credentials;
import java.util.UUID;
final class PasswordCredentialsTest {
#Test
void rejectsNullOwner() {
final Authenticatable owner = null;
final String password = Randomizr.INSTANCE.createRandomPassword();
Assertions.assertThrows(NullPointerException.class, () -> new PasswordCredentials(owner, password));
}
#Test
void rejectsNullPassword() {
final Authenticatable owner = new Authenticatable() {
#Override
public Credentials getCredentials() {
return null;
}
#Override
public UUID getID() {
return null;
}
};
final String password = null;
Assertions.assertThrows(NullPointerException.class, () -> new PasswordCredentials(owner, password));
}
#Test
void rejectsEmptyPassword() {
final Authenticatable owner = new Authenticatable() {
#Override
public Credentials getCredentials() {
return null;
}
#Override
public UUID getID() {
return null;
}
};
final String password = "";
Assertions.assertThrows(IllegalArgumentException.class, () -> new PasswordCredentials(owner, password));
}
#Test
void rejectsWhitespacePassword() {
final Authenticatable owner = new Authenticatable() {
#Override
public Credentials getCredentials() {
return null;
}
#Override
public UUID getID() {
return null;
}
};
final String password = "\t\t\n\n\n";
Assertions.assertThrows(IllegalArgumentException.class, () -> new PasswordCredentials(owner, password));
}
#Test
void hashCodeIsImplementedCorrectly() {
final Authenticatable owner = Fixtures.randomAuthenticatable();
final String password = Randomizr.INSTANCE.createRandomPassword();
final PasswordCredentials creds = new PasswordCredentials(owner, password);
final int firstHash = creds.hashCode();
final int secondHash = creds.hashCode();
Assertions.assertEquals(firstHash, secondHash);
final PasswordCredentials same = new PasswordCredentials(owner, password);
Assertions.assertEquals(creds.hashCode(), same.hashCode());
final PasswordCredentials different = new PasswordCredentials(owner, Randomizr.INSTANCE.createRandomPassword());
Assertions.assertNotEquals(firstHash, different.hashCode());
}
#Test
void equalsIsImplementedCorrectly() {
final Authenticatable owner = Fixtures.randomAuthenticatable();
final String password = Randomizr.INSTANCE.createRandomPassword();
final PasswordCredentials creds = new PasswordCredentials(owner, password);
Assertions.assertTrue(creds.equals(creds));
final PasswordCredentials same = new PasswordCredentials(owner, password);
Assertions.assertTrue(creds.equals(same));
Assertions.assertTrue(same.equals(creds));
final PasswordCredentials different = new PasswordCredentials(owner, Randomizr.INSTANCE.createRandomPassword());
Assertions.assertFalse(creds.equals(different));
Assertions.assertFalse(different.equals(creds));
}
}
hashCodeIsImplementedCorrectly() is failing in a way I don't expect: two objects that satisfy the equals contract are returning different hashcodes. This seems in direct violation of the JavaDoc:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
I'm just using Objects.hash in the recommended, IDE auto-generated manner...
This method is useful for implementing Object.hashCode() on objects containing multiple fields. For example, if an object that has three fields, x, y, and z, one could write:
#Override public int hashCode() {
return Objects.hash(x, y, z);
}
Am I missing something obvious? I haven't had this problem before, and written lots of unit tests for equals()/hashCode().
I shudder to think, but in case it's relevant...
java --version
openjdk 11.0.5 2019-10-15
OpenJDK Runtime Environment (build 11.0.5+10-post-Ubuntu-0ubuntu1.119.04)
OpenJDK 64-Bit Server VM (build 11.0.5+10-post-Ubuntu-0ubuntu1.119.04, mixed mode, sharing)
As you noted, if objects A and B are equal (in the sense that A.equals(B) returns true, they should have the same hash code. By extension, if you implement your equals method by checking the equality of a series of fields, using Objects.hash should provide a proper hashcode.
But this isn't what you're doing here - you're using Arrays.equals to compare two arrays - as you should. Arrays with the same contents are not equal, and thus may (and probably will) have different hash codes. Instead, you can use Arrays#hashCode to get value's hash code:
#Override
public int hashCode() {
return Objects.hash(owner, Arrays.hashCode(value));
// Here -------------------^
}
Looking at the generated equals method more closely gave it away: it's because value is a byte[]. When using arrays as fields, Objects.hash needs to use Arrays.hashCode(value).
This works correctly:
#Override
public int hashCode() {
return Objects.hash(owner, Arrays.hashCode(value));
}
I have such a Json :
{
"idcardno":"510525198803154232",
"name":"丁品"
}
If I use HmacSHA256 encrypt it with key
252c04cdb0d047f8ab9a1eb49b1db1686e321104756ff792779a4d40d94f0dfd70a8b9ffa6d6d930e57d0e7206d26d13
Then I should get such result:
cd1fe72697a832d57198b8c0d00289309dffe6f05750aa2a145f9359e41f1843
I need to encrypt this json object in java environemnt, so I use below java code to achieve this:
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONObject;
public class EncryptUtil {
// Charset to use when encrypting a string.
private static final String UTF_8 = "UTF-8";
// Encrypt key
private static final String APP_SECRET = "252c04cdb0d047f8ab9a1eb49b1db1686e321104756ff792779a4d40d94f0dfd70a8b9ffa6d6d930e57d0e7206d";
public static void main(String[] args) throws Exception {
//build json object
JSONObject object = new JSONObject();
object.put("idcardno", "510525198803154232");
object.put("name", "丁品");
String result = enCode(object.toString());
//print encrpted result
System.out.println(result);
}
public static String enCode(String orginalMsg) throws Exception {
try {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(APP_SECRET.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
String hash = Base64.encodeBase64String(sha256_HMAC.doFinal(orginalMsg.getBytes(UTF_8)));
return hash;
}
catch (Exception e){
throw new Exception(e);
}
}
}
But the encypted result is :
i2hF1WyxmS9MctkFLxBM2mgXeicraH9DhR9P9JySDFk=
How can get the correct result by Java code?
I'm trying to write a Java application with web3j that can read an arbitrary abi file, show the list of AbiDefinitions to the user and let him make a call to a constant function of his choice. How do I compute the outTypes below?
AbiDefinition functionDef = ...; // found at runtime
List<Type> args = ...; // I know how to do this
List<NamedType> outputs = functionDef.getOutputs(); // list of output parameters
List<TypeReference<?>> outTypes = ????;
Function function = new Function(functionDef.getName(), args, outTypes);
The TypeReference class uses tricks with generic types that work when the generic type is hardcoded in the source code like this:
new TypeReference.StaticArrayTypeReference< StaticArray< Int256>>(2){}
This is what the generated contract wrapper would do.
For simple types, I can do this:
Class<Type> type = (Class<Type>)AbiTypes.getType(typeName);
TypeReference<?> typeRef = TypeReference.create(type);
For array types like "int256[2]", what should I do?
uniswapV2 router
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)
package com.test;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.http.HttpService;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class main {
private static String EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
static Web3j web3j;
static String usdt = "0x55d398326f99059fF775485246999027B3197955";
static String weth = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
static String pancakeRouter = "0x10ed43c718714eb63d5aa57b78b54704e256024e";
public static void main(String[] args) throws IOException {
web3j = Web3j.build(new HttpService("https://bsc-dataseed.binance.org/"));
String s = web3j.netVersion().send().getNetVersion();
System.out.println(s);
List<BigInteger> list1 = getAmountsOut(usdt, weth);
System.out.println("result::: ");
for (BigInteger a : list1) {
System.out.println(a);
}
}
public static List<BigInteger> getAmountsOut(String tokenInAddr, String tokenOutAddr) {
String methodName = "getAmountsOut";
String fromAddr = EMPTY_ADDRESS;
List<Type> inputParameters = new ArrayList<Type>();
Uint256 inAmount = new Uint256(new BigInteger("1000000000000000000"));
Address inAddr = new Address(tokenInAddr);
Address outAddr = new Address(tokenOutAddr);
DynamicArray<Address> addrArr = new DynamicArray<Address>(inAddr, outAddr);
inputParameters.add(inAmount);
inputParameters.add(addrArr);
List<TypeReference<?>> outputParameters = new ArrayList<TypeReference<?>>();
TypeReference<DynamicArray<Uint256>> oa = new TypeReference<DynamicArray<Uint256>>() {
};
outputParameters.add(oa);
Function function = new Function(methodName, inputParameters, outputParameters);
String data = FunctionEncoder.encode(function);
Transaction transaction = Transaction.createEthCallTransaction(fromAddr, pancakeRouter, data);
EthCall ethCall;
try {
ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).sendAsync().get();
List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
System.out.println(results);
List<BigInteger> resultArr = new ArrayList<>();
if (results.size() > 0) {
for (Type tt : results) {
DynamicArray<Uint256> da = (DynamicArray<Uint256>) tt;
List<Uint256> lu = da.getValue();
if (lu.size() > 0) {
for (Uint256 n : lu) {
resultArr.add((BigInteger) n.getValue());
}
}
}
return resultArr;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
I have a function which generates pairs of keys for an array of users passed in (using RSA algorithm), it appears to generate the keys correctly for each user and adds them to an array list. However,when I'm trying to print the output,it appears to print only the last element. Can't seem to figure out what I'm doing wrong.
Here is the function which generates the keys and returns an arraylist:- it takes a string array of users as a parameter.
public static ArrayList<User> generateUserKeys(String [] users){
ArrayList <User> usrs = new ArrayList<User>();
KeyPair k;
for ( int i=0;i<users.length;i++)
{
k=generateKeyPair();
usrs.add(new User(users[i],k.getPublic(),k.getPrivate()));
System.out.println("User Name is :"+ usrs.get(i).getUserName());
System.out.println("Public Key is :"+ usrs.get(i).getPublicKey());
System.out.println("Private Key is :" + usrs.get(i).getPrivateKey());
}
return usrs;
}
Here is how I'm testing it:-
String [] users =
{"alisy#tcd.ie","yimk#tcd.ie","bachas#tcd.ie","tannerh#tcd.ie"};
ArrayList<User> usrz= generateUserKeys(users);
Iterator<User> itr = usrz.iterator();
while(itr.hasNext())
{
System.out.println(itr.next().getUserName());
}
The output I'm receiving is
tannerh#tcd.ie
tannerh#tcd.ie
tannerh#tcd.ie
tannerh#tcd.ie
I haven´t seen any problems in your generateUserKeys method code. Probably the User class is not ok, have you set the user name value as "tannerh#tcd.ie" inside the User class?
What is the result of the others System.out.println(...) lines? It should print "User Name is : tannerh#tcd.ie" four times too.
I tried running it as is, obviously there are few assumptions that I made in terms of what code has been used for User or KeyPairGenerator. Here is my code and I did not get the kind of output which was described in the problem. Can you help me to see if it has to do with static or something else? #PaulBoddington - Please do not treat this as judging what you have already said. I am posting this on basis of a testing I did. Caveat: I can be wrong here.
Source Code:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Iterator;
class User {
private String userName;
private PublicKey pubKey;
private PrivateKey privKey;
public User(String string, PublicKey public1, PrivateKey private1) {
userName = string;
pubKey = public1;
privKey = private1;
}
public String getUserName() {
return userName;
}
public String getPublicKey() {
return pubKey.toString();
}
public String getPrivateKey() {
return privKey.toString();
}
}
public class RSAKeyGenExample {
public static ArrayList<User> generateUserKeys(String[] users) throws NoSuchAlgorithmException {
ArrayList<User> usrs = new ArrayList<User>();
KeyPair k;
KeyPairGenerator keyGen = null;
keyGen = KeyPairGenerator.getInstance("RSA");
for (int i = 0; i < users.length; i++) {
k = keyGen.generateKeyPair();
usrs.add(new User(users[i], k.getPublic(), k.getPrivate()));
System.out.println("User Name is :" + usrs.get(i).getUserName());
System.out.println("Public Key is :" + usrs.get(i).getPublicKey());
System.out.println("Private Key is :" + usrs.get(i).getPrivateKey());
}
return usrs;
}
public static void main(String[] args) throws NoSuchAlgorithmException {
String[] users = { "alisy#tcd.ie", "yimk#tcd.ie", "bachas#tcd.ie", "tannerh#tcd.ie" };
ArrayList<User> usrz = generateUserKeys(users);
Iterator<User> itr = usrz.iterator();
while (itr.hasNext()) {
System.out.println(itr.next().getUserName());
}
}
}