package de.pinyto.ctSESAM;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Base64;
import android.util.Log;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.NoSuchPaddingException;
/**
* Stores and manages the key-generation-key.
*/
public class KgkManager {
private SharedPreferences savedDomains;
byte[] kgk;
byte[] iv2;
byte[] salt2;
Crypter kgkCrypter;
byte[] salt;
KgkManager(Context contentContext) {
this.savedDomains = contentContext.getSharedPreferences(
"savedDomains", Context.MODE_PRIVATE);
}
public byte[] getKgkCrypterSalt() {
byte[] salt = Base64.decode(
this.savedDomains.getString("salt", ""),
Base64.DEFAULT);
if (salt.length != 32) {
salt = Crypter.createSalt();
this.storeSalt(salt);
}
this.salt = salt;
return salt;
}
public void storeSalt(byte[] salt) {
this.salt = salt;
SharedPreferences.Editor savedDomainsEditor = this.savedDomains.edit();
savedDomainsEditor.putString("salt", Base64.encodeToString(
salt,
Base64.DEFAULT));
savedDomainsEditor.apply();
}
private Crypter getKgkCrypter(byte[] password, byte[] salt) {
this.kgkCrypter = new Crypter(Crypter.createIvKey(password, salt));
this.storeSalt(salt);
return this.kgkCrypter;
}
public byte[] createNewKgk() {
Clearer.zero(this.salt2);
Clearer.zero(this.iv2);
Clearer.zero(this.kgk);
SecureRandom sr = new SecureRandom();
this.kgk = new byte[64];
sr.nextBytes(this.kgk);
this.iv2 = Crypter.createIv();
this.salt2 = Crypter.createSalt();
return this.kgk;
}
public byte[] gelLocalKgkBlock() {
String kgkBase64 = this.savedDomains.getString("KGK", "");
if (kgkBase64.length() < 152) {
return new byte[]{};
}
return Base64.decode(kgkBase64, Base64.DEFAULT);
}
public void decryptKgk(Crypter kgkCrypter, byte[] encryptedKgk) {
this.kgkCrypter = kgkCrypter;
if (encryptedKgk.length != 112) {
createNewKgk();
} else {
try {
byte[] kgkBlock = kgkCrypter.decrypt(encryptedKgk, "NoPadding");
Clearer.zero(this.salt2);
Clearer.zero(this.iv2);
Clearer.zero(this.kgk);
this.salt2 = Arrays.copyOfRange(kgkBlock, 0, 32);
this.iv2 = Arrays.copyOfRange(kgkBlock, 32, 48);
this.kgk = Arrays.copyOfRange(kgkBlock, 48, 112);
} catch (NoSuchPaddingException paddingError) {
paddingError.printStackTrace();
}
}
}
public void decryptKgk(byte[] password, byte[] salt, byte[] encryptedKgk) {
this.salt = salt;
this.getKgkCrypter(password, salt);
this.decryptKgk(this.kgkCrypter, encryptedKgk);
}
public byte[] getKgk() {
return this.kgk;
}
public boolean hasKgk() {
return this.kgk != null && this.kgk.length == 64 && this.kgkCrypter != null;
}
public byte[] getSalt2() {
return this.salt2;
}
public byte[] getIv2() {
return this.iv2;
}
public void freshSalt2() {
Clearer.zero(this.salt2);
this.salt2 = Crypter.createSalt();
}
public void freshIv2() {
Clearer.zero(this.iv2);
this.iv2 = Crypter.createIv();
}
public byte[] getEncryptedKgk() {
byte[] kgkBlock = new byte[112];
System.arraycopy(this.salt2, 0, kgkBlock, 0, this.salt2.length);
System.arraycopy(this.iv2, 0, kgkBlock, salt2.length, this.iv2.length);
System.arraycopy(this.kgk, 0, kgkBlock, salt2.length + iv2.length, this.kgk.length);
byte[] encryptedKgk = this.kgkCrypter.encrypt(kgkBlock, "NoPadding");
Clearer.zero(kgkBlock);
return encryptedKgk;
}
public void createAndStoreNewKgkBlock(Crypter kgkCrypter) {
this.createNewKgk();
this.kgkCrypter = kgkCrypter;
this.freshIv2();
this.freshSalt2();
this.storeLocalKgkBlock();
}
public void updateFromBlob(byte[] password, byte[] blob) {
if (!(blob[0] == 0x01) || blob.length < 145) {
Log.d("Version error", "Wrong data format. Could not import anything.");
return;
}
byte[] salt = Arrays.copyOfRange(blob, 1, 33);
byte[] kgkBlock = Arrays.copyOfRange(blob, 33, 145);
this.decryptKgk(password, salt, kgkBlock);
}
public void storeLocalKgkBlock() {
SharedPreferences.Editor savedDomainsEditor = this.savedDomains.edit();
byte[] encryptedKgkBlock = this.getEncryptedKgk();
savedDomainsEditor.putString("KGK", Base64.encodeToString(
encryptedKgkBlock,
Base64.DEFAULT));
savedDomainsEditor.apply();
this.storeSalt(this.salt);
}
public void reset() {
this.salt = null;
this.iv2 = null;
this.salt2 = null;
this.kgk = null;
this.kgkCrypter = null;
}
}