package org.ovirt.engine.core.uutils.crypto.ticket; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.Signature; import java.security.cert.Certificate; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; import org.apache.commons.codec.binary.Base64; import org.codehaus.jackson.map.ObjectMapper; public class TicketEncoder { private static final String DATE_FORMAT = "yyyyMMddHHmmss"; private Certificate cert; private PrivateKey key; private final int lifetime; public TicketEncoder(Certificate cert, PrivateKey key, int lifetime) { this.lifetime = lifetime; this.cert = cert; this.key = key; } public TicketEncoder(Certificate cert, PrivateKey key) { this(cert, key, 5); } public String encode(String data) throws GeneralSecurityException, IOException { Base64 base64 = new Base64(0); Map<String, String> map = new HashMap<>(); byte[] random = new byte[8]; SecureRandom.getInstance("SHA1PRNG").nextBytes(random); map.put("salt", base64.encodeToString(random)); map.put("digest", "sha1"); DateFormat df = new SimpleDateFormat(DATE_FORMAT); df.setTimeZone(TimeZone.getTimeZone("UTC")); map.put( "validFrom", df.format(new Date()) ); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.add(Calendar.SECOND, lifetime); map.put( "validTo", df.format(cal.getTime()) ); map.put("data", data); /* * Calculate signature on fields in map */ Signature signature = Signature.getInstance(String.format("%swith%s", map.get("digest"), key.getAlgorithm())); signature.initSign(key); StringBuilder fields = new StringBuilder(); for (Map.Entry<String, String> entry : map.entrySet()) { if (fields.length() > 0) { fields.append(","); } fields.append(entry.getKey()); signature.update(entry.getValue().getBytes(StandardCharsets.UTF_8)); } /* * Add unsigned fields */ map.put("signedFields", fields.toString()); map.put("signature", base64.encodeToString(signature.sign())); map.put("certificate", String.format( "-----BEGIN CERTIFICATE-----\n" + "%s" + "-----END CERTIFICATE-----\n", new Base64(76).encodeToString(cert.getEncoded()) )); return base64.encodeToString(new ObjectMapper().writeValueAsString(map).getBytes(StandardCharsets.UTF_8)); } }