/*
* Copyright 2014 Christopher Mann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.uni_bonn.bit;
import android.os.Parcel;
import android.os.Parcelable;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.params.RegTestParams;
import org.apache.avro.io.BinaryDecoder;
import org.apache.avro.io.DecoderFactory;
import org.apache.avro.io.Encoder;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.reflect.AvroIgnore;
import org.apache.avro.reflect.ReflectDatumReader;
import org.apache.avro.reflect.ReflectDatumWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* This class stores the keys and parameters used by the two-party signature protocol. It is persisted with the help of
* avro, but it also implements {@link android.os.Parcelable} as it is also used to pass around the parameters between
* the different activities.
*/
public class KeyShareStore implements Parcelable {
private byte[] privateKey;
private byte[] otherPublicKey;
private PaillierKeyPair pkpDesktop;
private PaillierKeyPair pkpPhone;
private BCParameters desktopBCParameters;
private BCParameters phoneBCParameters;
@AvroIgnore
Address address;
public KeyShareStore(ECKey privateKey, ECKey otherPublicKey, PaillierKeyPair pkpDesktop, PaillierKeyPair pkpPhone,
BCParameters desktopBCParameters, BCParameters phoneBCParameters) {
this.privateKey = privateKey.getPrivKeyBytes();
this.otherPublicKey = otherPublicKey.getPubKey();
this.pkpDesktop = pkpDesktop;
this.pkpPhone = pkpPhone;
this.desktopBCParameters = desktopBCParameters;
this.phoneBCParameters = phoneBCParameters;
}
private KeyShareStore(){
}
public ECKey getPrivateKey() {
return ECKey.fromPrivate(privateKey);
}
public ECKey getOtherPublicKey() {
return ECKey.fromPublicOnly(otherPublicKey);
}
public PaillierKeyPair getPkpDesktop() {
return pkpDesktop;
}
public PaillierKeyPair getPkpPhone() {
return pkpPhone;
}
public BCParameters getDesktopBCParameters() {
return desktopBCParameters;
}
public BCParameters getPhoneBCParameters() { return phoneBCParameters; }
//---Parcelable serialization code ---
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByteArray(privateKey);
dest.writeByteArray(otherPublicKey);
dest.writeByteArray(serialize(pkpDesktop));
dest.writeByteArray(serialize(pkpPhone));
dest.writeByteArray(serialize(desktopBCParameters));
dest.writeByteArray(serialize(phoneBCParameters));
}
@AvroIgnore
public static final Parcelable.Creator<KeyShareStore> CREATOR
= new Parcelable.Creator<KeyShareStore>() {
public KeyShareStore createFromParcel(Parcel in) {
return new KeyShareStore(in);
}
public KeyShareStore[] newArray(int size) {
return new KeyShareStore[size];
}
};
private KeyShareStore(Parcel in) {
privateKey = in.createByteArray();
otherPublicKey = in.createByteArray();
pkpDesktop = (PaillierKeyPair) deserialize(in.createByteArray(), PaillierKeyPair.class);
pkpPhone = (PaillierKeyPair) deserialize(in.createByteArray(), PaillierKeyPair.class);
desktopBCParameters = (BCParameters) deserialize(in.createByteArray(), BCParameters.class);
phoneBCParameters = (BCParameters) deserialize(in.createByteArray(), BCParameters.class);
}
private static byte[] serialize(Object obj){
try{
ReflectDatumWriter writer = new ReflectDatumWriter<>(obj.getClass());
ByteArrayOutputStream bout = new ByteArrayOutputStream();
Encoder encoder = EncoderFactory.get().binaryEncoder(bout, null);
writer.write(obj, encoder);
encoder.flush();
return bout.toByteArray();
}catch(IOException e){
return null;
}
}
private Object deserialize(byte[] data, Class<?> clazz){
try{
ReflectDatumReader datumReader = new ReflectDatumReader<>(clazz);
BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(data, null);
return datumReader.read(null, decoder);
}catch(IOException e){
return null;
}
}
public String getAddressAsString() {
if(address == null){
address = BitcoinECMathHelper.convertPointToPubKEy(
BitcoinECMathHelper.convertPubKeyToPoint(getOtherPublicKey())
.multiply(BitcoinECMathHelper.convertPrivKeyToBigInt(getPrivateKey())
)).toAddress(RegTestParams.get());
}
return address.toString();
}
}