I am currently working on a encryption and decryption service for my application, using Google Tink.
The problem is the following: I want to program it without using (nearly) duplicate code and therefore I had the idea of using generics.
If parsing the Strings to a byte[] is the only option I will be doing that, but I'd rather not.
These are the methods & variables:
The 3 Stacks I am using:
private Stack<String> plaintextAccInformation = new Stack<>();
private Stack<byte[]> encryptedAccInformation = new Stack<>();
private Stack<String> decryptedAccInformation = new Stack<>();
private <T> Account getInformation(Stack<T> stack) {
boolean isApproved = stack.peek();
stack.pop();
boolean isAdmin = stack.peek();
stack.pop();
double balance = stack.peek();
stack.pop();
String password = stack.peek();
stack.pop();
String iBan = stack.peek();
stack.pop();
String uuid = stack.peek();
stack.pop();
return new Account(uuid, iBan, password, balance, isAdmin, isApproved);
}
public Account encrypt(Account account) throws GeneralSecurityException {
this.plaintextAccInformation.empty();
this.encryptedAccInformation.empty();
agjEncryption = new AesGcmJce(key.getBytes());
this.plaintextAccInformation.push(account.getUuid());
this.plaintextAccInformation.push(account.getIban());
this.plaintextAccInformation.push(account.getPassword());
this.plaintextAccInformation.push(String.valueOf(account.getBalance()));
this.plaintextAccInformation.push(String.valueOf(account.isAdmin()));
this.plaintextAccInformation.push(String.valueOf(account.isApproved()));
Iterator<String> iterator = plaintextAccInformation.iterator();
while (iterator.hasNext()) {
encryptedAccInformation.push(agjEncryption.encrypt(plaintextAccInformation.peek().getBytes(), aad.getBytes()));
plaintextAccInformation.pop();
}
return getInformation(this.encryptedAccInformation);
}
public Account decrypt() throws GeneralSecurityException {
this.decryptedAccInformation.empty();
this.agjDecryption = new AesGcmJce(key.getBytes());
Iterator<byte[]> iterator2 = encryptedAccInformation.iterator();
while (iterator2.hasNext()) {
decryptedAccInformation.push(new String(agjDecryption.decrypt(encryptedAccInformation.peek(), aad.getBytes())));
encryptedAccInformation.pop();
}
return getInformation(this.decryptedAccInformation);
}
Assuming you're sure the stack will always be in the order you expect here (which you seem to be).
Instead of a generic stack (which I believe limits you to only one value of T), you could use a stack of Object
and cast the results of the peek()
function.
private Account getInformation(Stack<Object> stack) {
Boolean isApproved = (Boolean) stack.peek();
stack.pop();
Boolean isAdmin = (Boolean) stack.peek();
stack.pop();
Double balance = (Double) stack.peek();
stack.pop();
String password = (String) stack.peek();
stack.pop();
String iBan = (String) stack.peek();
stack.pop();
String uuid = (String) stack.peek();
stack.pop();
return new Account(uuid, iBan, password, balance, isAdmin, isApproved);
}