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

com.sun.messaging.ums.service.SecuredSid Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2000, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2022 Contributors to Eclipse Foundation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.messaging.ums.service;

import com.sun.messaging.jmq.util.BASE64Decoder;
import com.sun.messaging.jmq.util.BASE64Encoder;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.util.UUID;
import java.util.logging.Logger;
import jakarta.jms.JMSException;

/**
 *
 * @author chiaming
 */
public class SecuredSid {

    private PrivateKey privateKey = null;

    private PublicKey publicKey = null;

    private Signature signer = null;

    private Signature verifier = null;

    private SecureRandom srandom = null;

    private long sequence = 0;

    private static BASE64Encoder encoder = null;

    private static BASE64Decoder decoder = null;

    private Logger logger = UMSServiceImpl.logger;

    private static final String UTF8 = "UTF-8";

    static {
        encoder = new BASE64Encoder();
        decoder = new BASE64Decoder();
    }

    public SecuredSid() throws JMSException {
        try {
            init();
        } catch (Exception e) {
            JMSException jmse = new JMSException(e.getMessage());
            jmse.setLinkedException(e);

            throw jmse;
        }
    }

    private void init() throws NoSuchAlgorithmException, InvalidKeyException {

        srandom = SecureRandom.getInstance("SHA1PRNG");

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");

        keyGen.initialize(1024, srandom);

        KeyPair pair = keyGen.generateKeyPair();

        // my private key to sign sid
        privateKey = pair.getPrivate();

        // my pub key to verify sid signature
        publicKey = pair.getPublic();

        signer = Signature.getInstance("SHA1withDSA");

        verifier = Signature.getInstance("SHA1withDSA");

        // init signature object -- i am ready to sign
        signer.initSign(privateKey);

        verifier.initVerify(this.publicKey);

    }

    /**
     * sid = sequence + "-" + (signature of sequence)
     */
    public synchronized String nextSid() throws JMSException {

        String sid = null;

        try {
            // 1. generate a secure random - 20 bytes
            // byte[] bytes = new byte[20];
            // this.srandom.nextBytes(bytes);

            if (this.sequence == Long.MAX_VALUE) {
                this.sequence = 0;
            }

            this.sequence++;

            // unique string in my domain
            String prefix = String.valueOf(sequence);

            // byte[] data = prefix.getBytes(UTF8);

            // This makes the original string hard to guess
            byte[] data = UUID.randomUUID().toString().getBytes(UTF8);

            // update what to sign
            signer.update(data);

            // sign data -- a secured string
            byte[] signature = this.signer.sign();

            // encode to base64
            String sigstr = encoder.encode(signature);

            // use signature hash
            int hash = sigstr.hashCode();
            byte[] scode = Integer.toString(hash).getBytes(UTF8);
            sigstr = encoder.encode(scode);
            // end hash

            // compose sid -- the sid is unique and secure!
            sid = prefix + "-" + sigstr;

        } catch (Exception e) {
            JMSException jmse = new JMSException(e.getMessage());
            jmse.setLinkedException(e);

            throw jmse;
        }

        if (UMSServiceImpl.debug) {
            logger.info("**** sid =" + sid + ", size=" + sid.length());
        }

        return sid;
    }

    public synchronized void verifySid(String sid) throws JMSException {

        try {

            // get sequence index
            int index = sid.indexOf('-');

            // get sequence
            String seq = sid.substring(0, index);

            index++;

            // get signature string - base 64
            String sigstr = sid.substring(index);

            if (UMSServiceImpl.debug) {
                logger.info("*** verifying sid, seq=" + seq + ",sig=" + sigstr + ", len=" + sigstr.length());
            }

            // get sequence bytes
            byte[] data = seq.getBytes(UTF8);

            // update what to verify
            this.verifier.update(data, 0, data.length);

            // decode signature from base64 to byte[]
            byte[] signature = decoder.decodeBuffer(sigstr);

            // verify signature
            boolean isvalid = this.verifier.verify(signature, 0, signature.length);

            if (isvalid == false) {
                throw new SecurityException("Invalid sid., sid = " + sid);
            }

            if (UMSServiceImpl.debug) {
                logger.info("*** sid is verified:" + isvalid + ", seq=" + seq + ",sig=" + sigstr);
            }

            // return isvalid;

        } catch (Exception e) {

            e.printStackTrace();
            JMSException jmse = new JMSException(e.getMessage());

            jmse.setLinkedException(e);

            throw jmse;
        }
    }

    public static String decode(String encodedString) throws JMSException {

        try {

            byte[] data = decoder.decodeBuffer(encodedString);

            String plain = new String(data, UTF8);

            return plain;

        } catch (IOException e) {

            JMSException jmse = new JMSException(e.getMessage());

            jmse.setLinkedException(e);

            throw jmse;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy