All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tozny.e3db.LocalEncryptedRecord Maven / Gradle / Ivy

There is a newer version: 7.2.3
Show newest version
/*
 * TOZNY NON-COMMERCIAL LICENSE
 *
 * Tozny dual licenses this product. For commercial use, please contact
 * [email protected]. For non-commercial use, the contents of this file are
 * subject to the TOZNY NON-COMMERCIAL LICENSE (the "License") which
 * permits use of the software only by government agencies, schools,
 * universities, non-profit organizations or individuals on projects that
 * do not receive external funding other than government research grants
 * and contracts.  Any other use requires a commercial license. You may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at https://tozny.com/legal/non-commercial-license.
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License. Portions of the software are Copyright (c) TOZNY LLC, 2018.
 * All rights reserved.
 *
 */

package com.tozny.e3db;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.io.IOException;
import java.util.*;

/**
 * An implementation of {@link EncryptedRecord} that can
 * be converted to a string (using {@link #encode()}) or loaded from
 * a string (using {@link #decode(String)}.
 */
public class LocalEncryptedRecord implements EncryptedRecord {
  private final Map data;
  private final ClientMeta meta;
  private final String signature;

  private static final ObjectMapper mapper;

  static {
    mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
  }

  /**
   * Create an instance with encrypted data, metadata, and the given signature.
   *
   * 

This constructor * should generally not be called directly; instead consider using {@link Client#encryptRecord(String, RecordData, Map, EAKInfo)} * or {@link Client#encryptExisting(LocalRecord, EAKInfo)}. * * @param data Encrypted data. Cannot be {@code null}. * @param meta Metadata associated with the record. Note that only server-specific metadata will be ignored (i.e, {@link RecordMeta#created()}, * {@link RecordMeta#lastModified()}, etc.). Cannot be {@code null}. * @param signature Signature of the plaintext data and metadata. Cannot be {@code null}. */ public LocalEncryptedRecord(Map data, ClientMeta meta, String signature) { this.data = data; this.meta = meta; this.signature = signature; } private static Map getMap(JsonNode data) { Map dataMap = new HashMap<>(); Iterator> fields = data.fields(); while(fields.hasNext()) { Map.Entry field = fields.next(); dataMap.put(field.getKey(), field.getValue().asText()); } return dataMap; } /** * Encode a record such that it can be decoded by {@link #decode(String)}. * @return Encoded representation of the record. */ public String encode() throws JsonProcessingException { HashMap meta1 = new HashMap<>(); meta1.put("type", meta().type()); if (meta().plain() != null) meta1.put("plain", meta().plain()); meta1.put("user_id", meta().userId().toString()); meta1.put("writer_id", meta().writerId().toString()); HashMap r = new HashMap<>(); r.put("data", data()); r.put("meta", meta1); r.put("rec_sig", signature()); return mapper.writeValueAsString(r); } /** * Decode a string produced by {@link #encode()} into a {@code LocalRecord} instance. Note that this does * not decrypt the record. * * @param record * @return The decoded record. * @throws IOException If the record cannot be decoded (missing values, ill-formed fields, or * an invalid encoding altogether). */ public static LocalEncryptedRecord decode(String record) throws IOException { JsonNode root = mapper.readTree(record); JsonNode data = root.get("data"); JsonNode meta = root.get("meta"); JsonNode signature = root.get("rec_sig"); if(data == null) throw new IOException("data field missing: " + record); if(meta == null) throw new IOException("meta field missing: " + record); try { Map dataMap = getMap(data); Map plain = meta.get("plain") != null ? getMap(meta.get("plain")) : null; LocalMeta clientMeta = new LocalMeta(UUID.fromString(meta.get("writer_id").asText()), UUID.fromString(meta.get("user_id").asText()), meta.get("type").asText(), plain); return new LocalEncryptedRecord(dataMap, clientMeta, signature.asText()); } catch (NullPointerException e) { throw new IOException("Field missing from record. Record: " + record, e); } catch (IllegalArgumentException e) { throw new IOException("A field could not be parsed. Record: " + record, e); } } @Override public ClientMeta meta() { return meta; } @Override public Map data() { return data; } @Override public String signature() { return signature; } @Override public String toSerialized() throws JsonProcessingException { SortedMap serializable = new TreeMap<>(); SortedMap metaMap = new TreeMap<>(); metaMap.put("type", meta.type()); metaMap.put("plain", meta.plain()); metaMap.put("user_id", meta.userId().toString()); metaMap.put("writer_id", meta.writerId().toString()); serializable.put("data", data()); serializable.put("meta", metaMap); serializable.put("rec_sig", signature()); return mapper.writeValueAsString(serializable); } @Override public LocalEncryptedRecord document() { return this; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy