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

org.finos.legend.engine.postgres.auth.SecureString Maven / Gradle / Ivy

There is a newer version: 4.66.0
Show newest version
// Copyright 2023 Goldman Sachs
//
//  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 org.finos.legend.engine.postgres.auth;

import java.io.Closeable;
import java.util.Arrays;
import java.util.Objects;

/**
 * A String implementations which allows clearing the underlying char array.
 */
public final class SecureString implements CharSequence, Closeable
{

    private char[] chars;

    /**
     * Constructs a new SecureString which controls the passed in char array.
     * 

* Note: When this instance is closed, the array will be zeroed out. */ public SecureString(char[] chars) { this.chars = Objects.requireNonNull(chars); } /** * Constant time equality to avoid potential timing attacks. */ @Override public synchronized boolean equals(Object o) { ensureNotClosed(); if (this == o) { return true; } if (o == null || o instanceof CharSequence == false) { return false; } CharSequence that = (CharSequence) o; if (chars.length != that.length()) { return false; } int equals = 0; for (int i = 0; i < chars.length; i++) { equals |= chars[i] ^ that.charAt(i); } return equals == 0; } @Override public synchronized int hashCode() { return Arrays.hashCode(chars); } @Override public synchronized int length() { ensureNotClosed(); return chars.length; } @Override public synchronized char charAt(int index) { ensureNotClosed(); return chars[index]; } @Override public SecureString subSequence(int start, int end) { throw new UnsupportedOperationException("Cannot get subsequence of SecureString"); } /** * Convert to a {@link String}. This should only be used with APIs that do not take {@link CharSequence}. */ @Override public synchronized String toString() { return new String(chars); } /** * Closes the string by clearing the underlying char array. */ @Override public synchronized void close() { if (chars != null) { Arrays.fill(chars, '\0'); chars = null; } } /** * Returns a new copy of this object that is backed by its own char array. Closing the new instance has no effect on the instance it * was created from. This is useful for APIs which accept a char array and you want to be safe about the API potentially modifying the * char array. For example: * *

     *     try (SecureString copy = secureString.clone()) {
     *         // pass thee char[] to a external API
     *         PasswordAuthentication auth = new PasswordAuthentication(username, copy.getChars());
     *         ...
     *     }
     * 
*/ @Override public synchronized SecureString clone() { ensureNotClosed(); return new SecureString(Arrays.copyOf(chars, chars.length)); } /** * Returns the underlying char[]. This is a dangerous operation as the array may be modified while it is being used by other threads * or a consumer may modify the values in the array. For safety, it is preferable to use {@link #clone()} and pass its chars to the * consumer when the chars are needed multiple times. */ public synchronized char[] getChars() { ensureNotClosed(); return chars; } /** * Throw an exception if this string has been closed, indicating something is trying to access the data after being closed. */ private void ensureNotClosed() { if (chars == null) { throw new IllegalStateException("SecureString has already been closed"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy