package jstellarapi.core;
import java.io.Serializable;
import java.util.Arrays;
import jstellarapi.keys.StellarBase58;
import org.bouncycastle.crypto.digests.SHA256Digest;
public class StellarIdentifier implements Serializable {
private static final long serialVersionUID = -6009723401818144454L;
String humanReadableIdentifier;
byte[] payloadBytes;
int identifierType;
/**
* @param payloadBytes
* @param identifierType : See ripple_data/protocol/RippleAddress.h
*/
public StellarIdentifier(byte[] payloadBytes, int identifierType){
this.payloadBytes = payloadBytes;
this.identifierType = identifierType;
}
public StellarIdentifier(String stringID) {
this.humanReadableIdentifier = stringID;
byte[] stridBytes = StellarBase58.decode(stringID);
byte[] checksumArray = doubleSha256(stridBytes, 0, stridBytes.length-4);
if( checksumArray[0]!=stridBytes[stridBytes.length-4]
|| checksumArray[1]!=stridBytes[stridBytes.length-3]
|| checksumArray[2]!=stridBytes[stridBytes.length-2]
|| checksumArray[3]!=stridBytes[stridBytes.length-1]){
throw new RuntimeException("Checksum failed on identifier "+stringID);
}
payloadBytes = Arrays.copyOfRange(stridBytes, 1, stridBytes.length-4);
identifierType = stridBytes[0];
}
@Override
public String toString() {
if(humanReadableIdentifier==null){
byte[] versionPayloadChecksumBytes=new byte[1+payloadBytes.length+4];
versionPayloadChecksumBytes[0]=(byte) identifierType;
System.arraycopy(payloadBytes, 0, versionPayloadChecksumBytes, 1, payloadBytes.length);
byte[] hashBytes = doubleSha256(versionPayloadChecksumBytes, 0, 1+payloadBytes.length);
System.arraycopy(hashBytes, 0, versionPayloadChecksumBytes, 1+payloadBytes.length, 4);
humanReadableIdentifier=StellarBase58.encode(versionPayloadChecksumBytes);
}
return humanReadableIdentifier;
}
protected byte[] doubleSha256(byte[] bytesToDoubleHash, int offset, int length) {
SHA256Digest mda = new SHA256Digest();
mda.update(bytesToDoubleHash, offset, length);
byte[] hashBytes = new byte[32];
mda.doFinal(hashBytes, 0);
mda.reset();
mda.update(hashBytes, 0, hashBytes.length);
mda.doFinal(hashBytes, 0);
return hashBytes;
}
public byte[] getBytes() {
return payloadBytes;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(payloadBytes);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StellarIdentifier other = (StellarIdentifier) obj;
if (!Arrays.equals(payloadBytes, other.payloadBytes))
return false;
return true;
}
}