package hamaster.gradesgin.ibe;
import static hamaster.gradesign.ibe.util.Hex.bytesToInt;
import static hamaster.gradesign.ibe.util.Hex.intToByte;
import hamaster.gradesgin.util.MemoryUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.security.PrivateKey;
import java.util.Arrays;
/**
* 用户私钥
* The private key
* @author <a href="mailto:wangyeee@gmail.com">Wang Ye</a>
*/
public class IBEPrivateKey implements Serializable, IBEConstraints, PrivateKey {
private static final long serialVersionUID = 1569046919144264563L;
/**
* 私钥rID部分
* rID part of private ley, length is 20 bytes;
*/
protected byte[] rID;
/**
* 私钥hID部分
* hID part ot private key, length is 128 bytes.
*/
protected byte[] hID;
/**
* 椭圆函数参数
* pairing
*/
private byte[] pairing;
/**
* 私钥所有者身份 即对应公钥
* the public key, e.g. email address
*/
private String userString;
public IBEPrivateKey() {
}
public byte[] getrID() {
return rID;
}
public void setrID(byte[] rID) {
this.rID = rID;
}
public byte[] gethID() {
return hID;
}
public void sethID(byte[] hID) {
this.hID = hID;
}
public String getUserString() {
return userString;
}
public void setUserString(String userString) {
this.userString = userString;
}
public byte[] getPairing() {
return pairing;
}
public void setPairing(byte[] pairing) {
this.pairing = pairing;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(hID);
result = prime * result + Arrays.hashCode(pairing);
result = prime * result + Arrays.hashCode(rID);
result = prime * result + ((userString == null) ? 0 : userString.hashCode());
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof IBEPrivateKey))
return false;
IBEPrivateKey other = (IBEPrivateKey) obj;
if (!Arrays.equals(hID, other.hID))
return false;
if (!Arrays.equals(pairing, other.pairing))
return false;
if (!Arrays.equals(rID, other.rID))
return false;
if (userString == null) {
if (other.userString != null)
return false;
} else if (!userString.equals(other.userString))
return false;
return true;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "IBEPrivateKey [rID=" + Arrays.toString(rID) + ", hID="
+ Arrays.toString(hID) + ", pairing="
+ Arrays.toString(pairing) + ", userString=" + userString + "]";
}
/*
* (non-Javadoc)
* @see java.security.Key#getAlgorithm()
*/
@Override
public String getAlgorithm() {
return "IBE";
}
/*
* (non-Javadoc)
* @see java.security.Key#getFormat()
*/
@Override
public String getFormat() {
return null;
}
/*
* (non-Javadoc)
* @see java.security.Key#getEncoded()
*/
@Override
public byte[] getEncoded() {
return null;
}
/**
* 写入顺序:<br>
* rID 20字节<br>
* hID 128字节<br>
* 用户字符串长度4字节<br>
* 用户字符串不定长度<br>
* 椭圆参数长度4字节<br>
* 椭圆参数不定长度
* Serialize the private key, this implementation writes key content directly to a file, keep it private!!!
* Sequence: rID - 20 bytes, hID - 128 bytes, length of public key - 4 bytes, public key, length of pairing - 4 bytes, pairing
* @see hamaster.gradesgin.ibe.IBEConstraints#writeExternal(java.io.OutputStream)
*/
@Override
public void writeExternal(OutputStream out) throws IOException {
byte[] encoded = getEncoded();
if (encoded != null) {
out.write(encoded);
out.flush();
return;
}
// 不编码,直接将私钥写入输出流
// TODO encrypt the private key with a password.
byte[] rBuffer = new byte[IBE_ZR_SIZE];
Arrays.fill(rBuffer, (byte) 0);
if (rID != null)
System.arraycopy(rID, 0, rBuffer, 0, IBE_ZR_SIZE > rID.length ? rID.length : IBE_ZR_SIZE);
out.write(rBuffer);
byte[] hBuffer = new byte[IBE_G_SIZE];
Arrays.fill(hBuffer, (byte) 0);
if (hID != null)
System.arraycopy(hID, 0, hBuffer, 0, IBE_G_SIZE > hID.length ? hID.length : IBE_G_SIZE);
out.write(hBuffer);
byte[] userBuffer = null;
if (userString != null) {
userBuffer = userString.getBytes(USER_STRING_ENCODING);
out.write(intToByte(userBuffer.length));
out.write(userBuffer);
}
byte[] pBuffer = new byte[IBE_G_SIZE * 4];
Arrays.fill(pBuffer, (byte) 0);
if (pairing != null) {
System.arraycopy(pairing, 0, pBuffer, 0, pairing.length);
out.write(intToByte(pairing.length));
} else {
out.write(intToByte(IBE_G_SIZE * 4));
}
out.write(pBuffer, 0, pairing == null ? pBuffer.length : pairing.length);
out.flush();
MemoryUtil.fastSecureBuffers(userBuffer, pBuffer);
MemoryUtil.immediateSecureBuffers(rBuffer, hBuffer);
}
/*
* (non-Javadoc)
* @see hamaster.gradesgin.ibe.IBEConstraints#readExternal(java.io.InputStream)
*/
@Override
public void readExternal(InputStream in) throws IOException, ClassNotFoundException {
// TODO 判断私钥是否是编码过的
byte[] buffer = new byte[IBE_ZR_SIZE + IBE_G_SIZE];
int keySize = in.read(buffer);
if (keySize != buffer.length)
throw new IOException("Not enough bytes for a PrivateKey");
this.rID = new byte[IBE_ZR_SIZE];
this.hID = new byte[IBE_G_SIZE];
System.arraycopy(buffer, 0, rID, 0, IBE_ZR_SIZE);
System.arraycopy(buffer, IBE_ZR_SIZE, hID, 0, IBE_G_SIZE);
byte[] upTmp = new byte[4];
Arrays.fill(upTmp, (byte) 0);
if (4 != in.read(upTmp)) {
throw new IOException("Not enough bytes for a PrivateKey");
}
int uSize = bytesToInt(upTmp);
byte[] uBuffer = new byte[uSize];
uSize = in.read(uBuffer);
if (uSize != uBuffer.length)
throw new IOException("Not enough bytes for a PrivateKey");
this.userString = new String(uBuffer, USER_STRING_ENCODING);
Arrays.fill(upTmp, (byte) 0);
if (4 != in.read(upTmp)) {
throw new IOException("Not enough bytes for a PrivateKey");
}
int pSize = bytesToInt(upTmp);
byte[] pBuffer = new byte[pSize];
pSize = in.read(pBuffer);
if (pSize != pBuffer.length)
throw new IOException("Not enough bytes for a PrivateKey pairing");
this.pairing = null;
if (pSize != IBE_G_SIZE * 4) {
this.pairing = new byte[pSize];
System.arraycopy(pBuffer, 0, pairing, 0, pSize);
}
MemoryUtil.fastSecureBuffers(pBuffer);
MemoryUtil.immediateSecureBuffers(buffer);
}
}