Arraylist only prints last added element - java

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());
}
}
}

Related

Trying to generate WM_SEC.AUTH_SIGNATURE (Walmart.io)

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

Can't generate RSA public key

I'm trying to learn about rsa public key generations. After some researches I create an "simple" code that should return a public key but I don't know why, it doesn't. Can anyone tell me why and explaine it?
public static byte[] GetTokens(String paramString) {
StringTokenizer stringTokenizer = new StringTokenizer(paramString, ",");
byte[] arrayOfByte = new byte[stringTokenizer.countTokens()];
for (byte b1 = 0; stringTokenizer.hasMoreTokens(); b1++) {
arrayOfByte[b1] = Byte.parseByte(stringTokenizer.nextToken());
}
return arrayOfByte;
}
public static PublicKey GenPublicKey() throws Exception {
BufferedReader bufferedReader = new BufferedReader(new FileReader("input_text"));
try {
String str1 = bufferedReader.readLine();
String str2 = bufferedReader.readLine();
BigInteger bigInteger1 = new BigInteger(GetTokens(str1));
BigInteger bigInteger2 = new BigInteger(GetTokens(str2));
RSAPublicKeySpec rSAPublicKeySpec = new RSAPublicKeySpec(bigInteger1, bigInteger2);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(rSAPublicKeySpec);
return publicKey;
}
catch (NoSuchAlgorithmException e) {
System.out.println("Exception thrown : " + e);
throw new IOException("Error reading key, ");
}
finally {
try {
bufferedReader.close();
} catch (Exception exception) {}
}
}
To testing it I wrote aleatory numbers on "input_text" file:
8,33
6,18
I will provide the code you need to generate a RSA public key:
import java.io.*;
import java.security.*;
import java.security.spec.*;
import java.util.*;
public class Hello {
public static void main(String[] args) throws NoSuchAlgorithmException {
// We generate an instance that allows to create private/public key pairs
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
// We use 1024 bits lenght
keyPairGenerator.initialize(2048);
// We generate key pair
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// Original message
String originalMessage = "Hello";
// We obtain public key
Key publicKey = keyPair.getPublic();
// We convert the string in order to send the Key to the emitter
String publicKeyText = keyToString(publicKey);
System.out.println("Public key: " + publicKeyText);
}
private static String keyToString(Key publicKey) {
byte[] publicKeyBytes = publicKey.getEncoded();
String key = Base64.getEncoder().encodeToString(publicKeyBytes);
return key;
}
}

How to use Java encrypt Json by HmacSHA256

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?

JNCryptor: Why does my call to decryptData not produce the correct result?

I need use the JNCryptor library in a project, so I am first trying to get a very simple example of encryption/decryption to work. My program just encrypts a short string, then decrypts it and displays the result. The problem is that I don't get the original text back. Here is the output when it runs:
C:\Java\JNCryptor_Test>java JNCryptorTest
Encrypted text: [B#2cfb4a64
Encrypted text back to plain text: [B#5474c6c
Can anyone tell me what I am doing wrong?
Here is the source code for my class JNCryptorTest:
import org.cryptonode.jncryptor.JNCryptor;
import org.cryptonode.jncryptor.AES256JNCryptor;
import org.cryptonode.jncryptor.CryptorException;
public class JNCryptorTest
{
private static String plaintext = "Hello, World!";
private static String password = "secretsquirrel";
public static void main(String[] args)
{
AllowAes256BitKeys.fixKeyLength();
byte[] encrypted = encrypt(plaintext);
System.out.println("Encrypted text: " + encrypted.toString());
String decrypted = decrypt(encrypted);
System.out.println("Encrypted text back to plain text: " + decrypted);
}
private static byte[] encrypt(String s)
{
JNCryptor cryptor = new AES256JNCryptor();
try
{
return cryptor.encryptData(s.getBytes(), password.toCharArray());
}
catch (CryptorException e)
{
// Something went wrong
e.printStackTrace();
return null;
}
}
private static String decrypt(byte[] msg)
{
JNCryptor cryptor = new AES256JNCryptor();
try
{
return (cryptor.decryptData(msg,
password.toCharArray())).toString();
}
catch (CryptorException e)
{
// Something went wrong
e.printStackTrace();
return null;
}
}
}
Also, I had to create the class AllowAes256BitKeys to allow 256-bit keys. It was recommended to install the "unlimited strength jurisdiction files" into the JVM, but that is unacceptable at our site, so I found a way to do it without that (see Java Security: Illegal key size or default parameters?).
Here is the source code for my class AllowAes256BitKeys:
import javax.crypto.Cipher;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
public class AllowAes256BitKeys
{
// From https://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters
public static void fixKeyLength()
{
String errorString =
"Unable to manually override key-length permissions.";
int newMaxKeyLength;
try
{
if ((newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES")) < 256)
{
Class<?> c =
Class.forName("javax.crypto.CryptoAllPermissionCollection");
Constructor con = c.getDeclaredConstructor();
con.setAccessible(true);
Object allPermissionCollection = con.newInstance();
Field f = c.getDeclaredField("all_allowed");
f.setAccessible(true);
f.setBoolean(allPermissionCollection, true);
c = Class.forName("javax.crypto.CryptoPermissions");
con = c.getDeclaredConstructor();
con.setAccessible(true);
Object allPermissions = con.newInstance();
f = c.getDeclaredField("perms");
f.setAccessible(true);
// Warnings suppressed because CryptoPermissions uses a raw Map
#SuppressWarnings({"unchecked"})
Object junk = // Only need this so we can use #SuppressWarnings
((Map) f.get(allPermissions)).put("*", allPermissionCollection);
// ((Map) f.get(allPermissions)).put("*", allPermissionCollection);
c = Class.forName("javax.crypto.JceSecurityManager");
f = c.getDeclaredField("defaultPolicy");
f.setAccessible(true);
Field mf = Field.class.getDeclaredField("modifiers");
mf.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.set(null, allPermissions);
newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");
}
}
catch (Exception e)
{
throw new RuntimeException(errorString, e);
}
if (newMaxKeyLength < 256)
throw new RuntimeException(errorString); // hack failed
}
}
Thanks
However, I was able to resolve this myself with some help from a more experienced Java developer. It turns out that there was no issue with JNCryptor; the problem is that I was converting the decrypted result (a byte array) into a String incorrectly. The toString method is not the correct way to do that; you have to create a new String object and pass the byte array to its constructor.
So I changed this line in my decrypt method
return (cryptor.decryptData(msg, password.toCharArray())).toString();
to this
return (new String(cryptor.decryptData(msg, password.toCharArray())));
and then I got the correct result:
Encrypted text: [B#2cfb4a64
Encrypted text back to plain text: Hello, World!
So actually, JNCryptor was working correctly the whole time- It was my code which displayed the result that was the problem.

Java password-based encryption fails on Linux

I need help figuring out why Java encryption fails on my machine running Linux Mint 17.2 Rafaela. My application is not able to decrypt previously encrypted values using the RC4 algorithm.
I am testing with Java 8 u112 and I installed the JCE, but that did not help.
Here is the minimum sample I created, which works on my Windows machine:
import javax.xml.bind.DatatypeConverter;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class CryptoTest
{
private static final String ADMIN_PASSWORD = "admin";
private static final String ADMIN_ENCRYPTED_PASSWORD = "532C05C5B5"; // RC4 encrypted password using KEY
private static final String ADMIN_AUTH_KEY = "1391a8a860b7d6e2e86df513700e490c16dae47cdae227ca"; // PBKDF2(username,password,salt)
private static final String CRYPTO_ALGORITHM = "RC4";
protected static String encryptPassword(String passwordDataToEncrypt, String userskey) throws Exception
{
SecureRandom sr = new SecureRandom(userskey.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(CRYPTO_ALGORITHM);
kg.init(sr);
SecretKey sk = kg.generateKey();
Cipher cipher = Cipher.getInstance(CRYPTO_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, sk);
return bytesToHex(cipher.doFinal(passwordDataToEncrypt.getBytes()));
}
private static String bytesToHex(byte[] in)
{
return DatatypeConverter.printHexBinary(in);
}
private static byte[] hexStringToByteArray(String s)
{
return DatatypeConverter.parseHexBinary(s);
}
protected static String decryptPassword(byte[] toDecryptPassword, String key) throws Exception
{
SecureRandom sr = new SecureRandom(key.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(CRYPTO_ALGORITHM);
kg.init(sr);
SecretKey sk = kg.generateKey();
Cipher cipher = Cipher.getInstance(CRYPTO_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, sk);
return new String(cipher.doFinal(toDecryptPassword));
}
public static void assertEquals(String arg1, String arg2)
{
if (! arg1.equals(arg2))
{
System.out.println(String.format("%s does not equal %s", arg1, arg2));
}
}
public static void testGetDecryptedPassword() throws Exception
{
String decryptedPassword = decryptPassword(hexStringToByteArray(ADMIN_ENCRYPTED_PASSWORD), ADMIN_AUTH_KEY);
assertEquals(ADMIN_PASSWORD, decryptedPassword);
}
public static void testGetEncryptedPassword() throws Exception
{
String encryptedPassword = encryptPassword(ADMIN_PASSWORD, ADMIN_AUTH_KEY);
assertEquals(ADMIN_ENCRYPTED_PASSWORD, encryptedPassword);
}
public static void testEncryptAndDecryptPasswords() throws Exception
{
String originalPassword = "password";
String encryptedPassword = encryptPassword(originalPassword, ADMIN_AUTH_KEY);
String decryptedPassword = decryptPassword(hexStringToByteArray(encryptedPassword), ADMIN_AUTH_KEY);
assertEquals(originalPassword, decryptedPassword);
originalPassword = "This is a STRONG password 4 me!!!##$^";
encryptedPassword = encryptPassword(originalPassword, ADMIN_AUTH_KEY);
decryptedPassword = decryptPassword(hexStringToByteArray(encryptedPassword), ADMIN_AUTH_KEY);
assertEquals(originalPassword, decryptedPassword);
}
public static void main(final String[] args)
{
try
{
int strength = Cipher.getMaxAllowedKeyLength("AES");
if ( strength > 128 ){
System.out.printf("isUnlimitedSupported=TRUE,strength: %d%n",strength);
} else {
System.out.printf("isUnlimitedSupported=FALSE,strength: %d%n",strength);
}
testGetDecryptedPassword();
testGetEncryptedPassword();
testEncryptAndDecryptPasswords();
}
catch (Exception e)
{
System.out.printf("Caught exception: %s\n", e.getMessage());
e.printStackTrace(System.out);
}
}
}
The output on my linux box is:
isUnlimitedSupported=TRUE,strength: 2147483647
admin does not equal <junk>
532C05C5B5 does not equal 5D16D89D2F
password does not equal <junk>
This is a STRONG password 4 me!!!##$^ does not equal <junk>
Where <junk> is a bunch of unprintable chars.
Your code assumes that you get the same SecretKey each time you initialize your SecureRandom() with the same password in the following code:
SecureRandom sr = new SecureRandom(userskey.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(CRYPTO_ALGORITHM);
kg.init(sr);
SecretKey sk = kg.generateKey();
You really can't make that assumption, and you should not use that approach. The SecureRandom is part of the JCA architecture where the actual implementation you get when you instantiates a new SecureRandom(..) depends on which security providers are available on your system, and which priority each provider have.
If you need to make encryption keys from passwords, you should use a key derivation function invented for that like PBKDF2.

Categories