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

com.swirlds.common.crypto.SerializablePublicKey Maven / Gradle / Ivy

Go to download

Swirlds is a software platform designed to build fully-distributed applications that harness the power of the cloud without servers. Now you can develop applications with fairness in decision making, speed, trust and reliability, at a fraction of the cost of traditional server-based platforms.

There is a newer version: 0.56.6
Show newest version
/*
 * Copyright (C) 2019-2024 Hedera Hashgraph, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.swirlds.common.crypto;

import static com.swirlds.common.utility.CommonUtils.hex;

import com.swirlds.base.utility.ToStringBuilder;
import com.swirlds.common.io.SelfSerializable;
import com.swirlds.common.io.streams.SerializableDataInputStream;
import com.swirlds.common.io.streams.SerializableDataOutputStream;
import com.swirlds.logging.legacy.LogMarker;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

public class SerializablePublicKey implements SelfSerializable {
    private static final long CLASS_ID = 0x2554c14f4f61cd9L;
    private static final int CLASS_VERSION = 2;
    private static final int MAX_KEY_LENGTH = 6_144;
    private static final int MAX_ALG_LENGTH = 10;

    private PublicKey publicKey;
    private KeyType keyType;

    public SerializablePublicKey() {}

    public SerializablePublicKey(PublicKey publicKey) {
        if (publicKey == null) {
            // null will not be supported for the time being, or maybe never
            throw new IllegalArgumentException("publicKey must not be null!");
        }
        this.publicKey = publicKey;
        this.keyType = KeyType.getKeyType(publicKey);
    }

    /**
     * Getter that the returns the underlying JCE {@link PublicKey} implementation.
     *
     * @return the public key
     */
    public PublicKey getPublicKey() {
        return publicKey;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getVersion() {
        return CLASS_VERSION;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void serialize(SerializableDataOutputStream out) throws IOException {
        out.writeInt(keyType.getAlgorithmIdentifier());
        out.writeByteArray(publicKey.getEncoded());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void deserialize(SerializableDataInputStream in, int version) throws IOException {
        if (version == 1) {
            String algorithm = in.readNormalisedString(MAX_ALG_LENGTH);
            keyType = KeyType.valueOf(algorithm);
        } else {
            keyType = KeyType.getKeyType(in.readInt());
        }
        byte[] keyBytes = in.readByteArray(MAX_KEY_LENGTH);
        publicKey = bytesToPublicKey(keyBytes, keyType.getAlgorithmName());
    }

    /**
     * Converts an encoded public key representation from the given {@code bytes} argument to a {@link PublicKey}
     * instance.
     *
     * @param bytes
     * 		the encoded public key
     * @param keyType
     * 		the JCE key algorithm identifier
     * @return the public key
     * @throws CryptographyException
     * 		if the algorithm is not available or the encoded key is invalid
     */
    public static PublicKey bytesToPublicKey(byte[] bytes, String keyType) {
        try {
            EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(bytes);
            KeyFactory keyFactory = KeyFactory.getInstance(keyType);
            return keyFactory.generatePublic(publicKeySpec);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
            throw new CryptographyException(ex, LogMarker.EXCEPTION);
        }
    }

    /**
     * A method used to deserialize a public key before if had a version number
     *
     * @param in
     * 		the stream to read from
     * @param algorithm
     * 		the algorithm of the key, this was not stored in the stream before
     * @throws IOException
     * 		thrown if an IO error happens
     */
    public void deserializeVersion0(SerializableDataInputStream in, String algorithm) throws IOException {
        keyType = KeyType.valueOf(algorithm);
        byte[] keyBytes = in.readByteArray(MAX_KEY_LENGTH);
        publicKey = bytesToPublicKey(keyBytes, algorithm);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        SerializablePublicKey that = (SerializablePublicKey) o;
        return publicKey.equals(that.publicKey) && keyType == that.keyType;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getClassId() {
        return CLASS_ID;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return new ToStringBuilder(this)
                .append("publicKey", hex(publicKey.getEncoded()))
                .append("keyType", keyType)
                .toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy