package hamaster.gradesgin.ibs;
import static hamaster.gradesign.ibe.util.Hex.bytesToInt;
import static hamaster.gradesign.ibe.util.Hex.bytesToLong;
import static hamaster.gradesign.ibe.util.Hex.intToByte;
import static hamaster.gradesign.ibe.util.Hex.longToBytes;
import hamaster.gradesgin.ibe.IBEConstraints;
import hamaster.gradesgin.ibe.IBEPrivateKey;
import hamaster.gradesgin.ibe.IBEPublicParameter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
/**
* IBS数字签名
* @author <a href="mailto:wangyeee@gmail.com">Wang Ye</a>
*/
public class IBSSignature extends IBEPrivateKey implements Serializable, IBEConstraints {
private static final long serialVersionUID = -4862591033031464057L;
/**
* 签名者参数
*/
protected IBEPublicParameter signatureParameter;
/**
* 被签名数据的摘要
*/
protected byte[] digest;
/**
* 摘要算法
*/
protected String hashAlgorithm;
/**
* 签名日期
*/
protected Date signingDate;
public IBSSignature() {
}
public IBEPublicParameter getSignatureParameter() {
return signatureParameter;
}
public void setSignatureParameter(IBEPublicParameter signatureParameter) {
this.signatureParameter = signatureParameter;
setPairing(signatureParameter.getPairing());
}
public byte[] getDigest() {
return digest;
}
public void setDigest(byte[] digest) {
this.digest = digest;
}
public String getHashAlgorithm() {
return hashAlgorithm;
}
public void setHashAlgorithm(String hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}
public Date getSigningDate() {
return signingDate;
}
public void setSigningDate(Date signingDate) {
this.signingDate = signingDate;
}
/**
* 序列化字段:<br>
* rID 20字节<br>
* hID 128字节<br>
* 摘要长度 4字节<br>
* 摘要内容<br>
* 签名参数<br>
* 签名日期 8字节<br>
* 哈希算法长度 1字节<br>
* 哈希算法字符串
* @see hamaster.gradesgin.ibe.IBEConstraints#writeExternal(java.io.OutputStream)
*/
@Override
public void writeExternal(OutputStream out) throws IOException {
byte[] rBuffer = new byte[IBE_ZR_SIZE];
byte[] hBuffer = new byte[IBE_G_SIZE];
Arrays.fill(rBuffer, (byte) 0);
Arrays.fill(hBuffer, (byte) 0);
if (rID != null)
System.arraycopy(rID, 0, rBuffer, 0, rID.length > IBE_ZR_SIZE ? IBE_ZR_SIZE : rID.length);
out.write(rBuffer);
if (hID != null)
System.arraycopy(hID, 0, hBuffer, 0, hID.length > IBE_G_SIZE ? IBE_G_SIZE : hID.length);
out.write(hBuffer);
if (digest == null) {
byte[] zero = new byte[4];
Arrays.fill(zero, (byte) 0);
out.write(zero);
} else {
out.write(intToByte(digest.length));
out.write(digest);
}
signatureParameter.writeExternal(out);
if (signingDate == null) {
byte[] zero = new byte[8];
Arrays.fill(zero, (byte) 0);
out.write(zero);
} else {
out.write(longToBytes(signingDate.getTime()));
}
int aSize = hashAlgorithm == null ? 0 : hashAlgorithm.length();
out.write((byte) aSize);
out.write(hashAlgorithm.getBytes(USER_STRING_ENCODING));
out.flush();
}
/*
* (non-Javadoc)
* @see hamaster.gradesgin.ibe.IBEConstraints#readExternal(java.io.InputStream)
*/
@Override
public void readExternal(InputStream in) throws IOException, ClassNotFoundException {
byte[] buffer = new byte[IBE_G_SIZE + IBE_ZR_SIZE];
int size = in.read(buffer);
if (size != buffer.length)
throw new IOException("Not enough bytes for a Signature");
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[] dTmp = new byte[4];
Arrays.fill(dTmp, (byte) 0);
if (4 != in.read(dTmp))
throw new IOException("Not enough bytes for a Signature");
int dSize = bytesToInt(dTmp);
this.digest = new byte[dSize];
dSize = in.read(digest);
if (dSize != digest.length)
throw new IOException("Not enough bytes for a Signature");
setUserString(new String(digest, USER_STRING_ENCODING));
this.signatureParameter = new IBEPublicParameter();
signatureParameter.readExternal(in);
byte[] sTmp = new byte[8];
Arrays.fill(sTmp, (byte) 0);
if (8 != in.read(sTmp))
throw new IOException("Not enough bytes for a Signature");
this.signingDate = new Date(bytesToLong(sTmp));
size = in.read();
byte[] hash = new byte[size];
size = in.read(hash);
if (size != hash.length)
throw new IOException("Not enough bytes for a Signature");
this.hashAlgorithm = new String(hash, 0, size, USER_STRING_ENCODING);
setPairing(signatureParameter.getPairing());
}
}