/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.github.horrorho.inflatabledonkey.cache; import com.dd.plist.NSData; import com.dd.plist.NSDictionary; import com.dd.plist.NSString; import com.dd.plist.PropertyListFormatException; import com.dd.plist.PropertyListParser; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.text.ParseException; import java.util.Arrays; import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import javax.xml.parsers.ParserConfigurationException; import javax.annotation.concurrent.NotThreadSafe; import org.bouncycastle.util.encoders.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; /** * * @author Ayesha */ @NotThreadSafe public final class InflatableData { public static InflatableData generate() { UUID deviceID = UUID.randomUUID(); String deviceHardwareID = new BigInteger(256, ThreadLocalRandom.current()).toString(16).toUpperCase(Locale.US); return new InflatableData(deviceID, deviceHardwareID); } public static Optional<InflatableData> from(byte[] bs) { InflatableData data; try { NSDictionary parse = (NSDictionary) PropertyListParser.parse(bs); byte[] escrowedKeys = ((NSData) parse.get("escrowedKeys")).bytes(); UUID deviceUuid = UUID.fromString(((NSString) parse.get("deviceUuid")).getContent()); String deviceHardWareId = ((NSString) parse.get("deviceHardWareId")).getContent(); data = new InflatableData(escrowedKeys, deviceUuid, deviceHardWareId); } catch (ClassCastException | IllegalArgumentException | IOException | NullPointerException | PropertyListFormatException | ParseException | ParserConfigurationException | SAXException ex) { logger.warn("-- from() - exception: ", ex); data = null; } return Optional.ofNullable(data); } private static final Logger logger = LoggerFactory.getLogger(InflatableData.class); private byte[] escrowedKeys; private UUID deviceUuid; private String deviceHardWareId; public InflatableData(byte[] escrowedKeys, UUID deviceUuid, String deviceHardWareId) { this.escrowedKeys = Arrays.copyOf(escrowedKeys, escrowedKeys.length); this.deviceUuid = Objects.requireNonNull(deviceUuid); this.deviceHardWareId = Objects.requireNonNull(deviceHardWareId); } public InflatableData(UUID deviceUuid, String deviceHardWareId) { this(new byte[]{}, deviceUuid, deviceHardWareId); } public byte[] encoded() { try { NSDictionary dict = new NSDictionary(); dict.put("escrowedKeys", new NSData(escrowedKeys)); dict.put("deviceUuid", new NSString(deviceUuid.toString())); dict.put("deviceHardWareId", new NSString(deviceHardWareId)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PropertyListParser.saveAsBinary(dict, baos); return baos.toByteArray(); } catch (IOException ex) { throw new IllegalStateException(ex); } } public boolean hasEscrowedKeys() { return escrowedKeys.length > 0; } public byte[] escrowedKeys() { return Arrays.copyOf(escrowedKeys, escrowedKeys.length); } public void setEscrowedKeys(byte[] escrowedKeys) { this.escrowedKeys = Arrays.copyOf(escrowedKeys, escrowedKeys.length); } public UUID deviceUuid() { return deviceUuid; } public void setDeviceUuid(UUID deviceUuid) { this.deviceUuid = deviceUuid; } public String deviceHardWareId() { return deviceHardWareId; } public void setDeviceHardWareId(String deviceHardWareId) { this.deviceHardWareId = deviceHardWareId; } @Override public String toString() { return "InflatableData{" + "escrowedKeys=0x" + Hex.toHexString(escrowedKeys) + ", deviceUuid=" + deviceUuid + ", deviceHardWareId=" + deviceHardWareId + '}'; } }