package hamaster.gradesgin.ibe;
import hamaster.gradesgin.util.MemoryUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Arrays;
/**
* 明文
* @author <a href="mailto:wangyeee@gmail.com">Wang Ye</a>
*/
public class IBEPlainText implements IBEConstraints, Serializable {
private static final long serialVersionUID = -2705082103669151761L;
/**
* 明文内容 长度128字节
* Length of plain text, max 128 bytes
*/
private byte[] content;
/**
* 明文的有效长度 最大为126
* Max length of mutable plain text, 126 bytes.
* The first and 64th byte must be zero to avoid overflow.
*/
private int length;
// TODO protected
public IBEPlainText() {
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
public void setLength(int length) {
this.length = length;
}
public int getLength() {
return length;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(content);
result = prime * result + length;
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 IBEPlainText))
return false;
IBEPlainText other = (IBEPlainText) obj;
if (!Arrays.equals(content, other.content))
return false;
if (length != other.length)
return false;
return true;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "IBEPlainText [content=" + Arrays.toString(content)
+ ", length=" + getLength() + "]";
}
/**
* 获取解密后明文中的有效内容
* Get the 126 bytes content of decrypted plain text
* @param plainText 要获取的明文
* @return 包含有效内容的字节数组(Byte array containing the plain text)
*/
public static byte[] getSignificantBytes(IBEPlainText plainText) {
synchronized (plainText) {
byte[] plain = new byte[plainText.getLength()];
final int IBE_HALF = IBE_G_SIZE / 2 - 1;
if (plainText.getLength() > IBE_HALF) {
System.arraycopy(plainText.content, IBE_G_SIZE - plainText.getLength() - 1, plain, 0, plainText.getLength() - IBE_HALF);
System.arraycopy(plainText.content, IBE_G_SIZE - IBE_HALF, plain, plainText.getLength() - IBE_HALF, IBE_HALF);
} else {
System.arraycopy(plainText.content, IBE_G_SIZE - plainText.getLength(), plain, 0, plainText.getLength());
}
return plain;
}
}
/**
* 通过特定长度的字节构建IBEPlainText对象
* Construct an IBEPlainText object from certain length of bytes, the length must be from 1 to 126
* @param significantBytes 有效字节 长度在1到126字节中间
* @return IBEPlainText
*/
public static IBEPlainText newIbePlainTextFormSignificantBytes(byte[] significantBytes) {
IBEPlainText text = new IBEPlainText();
if (significantBytes == null || significantBytes.length == 0 || significantBytes.length > IBE_G_SIZE - 2)
throw new IllegalArgumentException("invalid plain text");
int length = significantBytes.length;
final int IBE_HALF = IBE_G_SIZE / 2 - 1;
text.content = new byte[IBE_G_SIZE];
Arrays.fill(text.content, (byte) 0);
if (length > IBE_HALF) {
System.arraycopy(significantBytes, 0, text.content, IBE_G_SIZE - length - 1, length - IBE_HALF);
System.arraycopy(significantBytes, length - IBE_HALF, text.content, IBE_G_SIZE - IBE_HALF, IBE_HALF);
} else {
System.arraycopy(significantBytes, 0, text.content, IBE_G_SIZE - length, length);
}
text.setLength(length);
return text;
}
/**
* 序列化字段:<br>
* 明文内容 128字节<br>
* 明文有效长度 1字节<br>
* Serialize this object, the first 128 bytes are padded plain text and the last byte is the length of byte used(1 to 126)
* @see hamaster.gradesgin.ibe.IBEConstraints#writeExternal(java.io.OutputStream)
*/
@Override
public void writeExternal(OutputStream out) throws IOException {
byte[] contentBuffer = new byte[IBE_G_SIZE];
Arrays.fill(contentBuffer, (byte) 0);
if (content != null)
System.arraycopy(content, 0, contentBuffer, 0, IBE_G_SIZE > content.length ? content.length : IBE_G_SIZE);
out.write(contentBuffer);
out.write((byte) getLength());
out.flush();
MemoryUtil.immediateSecureBuffers(contentBuffer);
}
/*
* (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];
int size = in.read(buffer);
if (size != buffer.length)
throw new IOException("Not enough bytes for a PlainText");
this.content = new byte[IBE_G_SIZE];
System.arraycopy(buffer, 0, content, 0, IBE_G_SIZE);
this.setLength(in.read());
MemoryUtil.immediateSecureBuffers(buffer);
}
}