001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2015 ForgeRock AS.
015 */
016
017package org.forgerock.openig.handler;
018
019import java.security.NoSuchAlgorithmException;
020import java.util.HashMap;
021import java.util.Map;
022
023import javax.crypto.KeyGenerator;
024import javax.crypto.SecretKey;
025
026import org.forgerock.http.Handler;
027import org.forgerock.http.protocol.Request;
028import org.forgerock.http.protocol.Response;
029import org.forgerock.http.protocol.Status;
030import org.forgerock.openig.heap.GenericHeapObject;
031import org.forgerock.openig.heap.GenericHeaplet;
032import org.forgerock.openig.heap.HeapException;
033import org.forgerock.services.context.Context;
034import org.forgerock.util.encode.Base64;
035import org.forgerock.util.promise.NeverThrowsException;
036import org.forgerock.util.promise.Promise;
037import org.forgerock.util.promise.Promises;
038
039/**
040 * Creates a static response with a generated DES key.
041 *
042 * <br>
043 *
044 * This handler takes no configuration settings.
045 *
046 * <pre>
047 * {@code
048 * {
049 *   "name": "KeyGenerator",
050 *   "type": "DesKeyGenHandler"
051 * }
052 * }
053 * </pre>
054 *
055 * When called, it generates a base64-encoded DES key,
056 * and returns the "key" value in a JSON response:
057 *
058 * <pre>{@code {"key":"/R/9khUxnaQ="}}</pre>
059 *
060 * If the handler fails to find a key generator for DES keys,
061 * then it does not return a "key", but instead returns an "error":
062 *
063 * <pre>{@code {"error":"Failed to generate a key: ..."}}</pre>
064 */
065public class DesKeyGenHandler extends GenericHeapObject implements Handler {
066
067    /**
068     * Generate a base64-encoded DES key.
069     *
070     * @return  On success, a Map with key "key" whose value is the encoded key.
071     *          On failure, a Map with key "error" whose value is an error message.
072     */
073    private Map<String, String> getSharedKey() {
074        Map<String, String> sharedKey = new HashMap<>();
075        try {
076            KeyGenerator generator = KeyGenerator.getInstance("DES");
077            SecretKey key = generator.generateKey();
078            sharedKey.put("key", Base64.encode(key.getEncoded()));
079        } catch (NoSuchAlgorithmException e) {
080            sharedKey.put("error", "Failed to generate a key: " + e.getMessage());
081        }
082        return sharedKey;
083    }
084
085    @Override
086    public Promise<Response, NeverThrowsException> handle(final Context context, final Request request) {
087        Response response = new Response();
088        response.setStatus(Status.OK);
089        response.setEntity(getSharedKey());
090        return Promises.newResultPromise(response);
091    }
092
093    /**
094     * Creates and initializes a DES key generator handler in a heap environment.
095     */
096    public static class Heaplet extends GenericHeaplet {
097        @Override
098        public Object create() throws HeapException {
099            return new DesKeyGenHandler();
100        }
101    }
102}