com.yubico.webauthn.data.ByteArray Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webauthn-server-core Show documentation
Show all versions of webauthn-server-core Show documentation
Yubico WebAuthn server core API
// Copyright (c) 2018, Yubico AB
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.yubico.webauthn.data;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.primitives.Bytes;
import com.yubico.internal.util.BinaryUtil;
import com.yubico.webauthn.data.exception.Base64UrlException;
import com.yubico.webauthn.data.exception.HexException;
import java.util.Base64;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
/** An immutable byte array with support for encoding/decoding to/from various encodings. */
@EqualsAndHashCode
@ToString(includeFieldNames = false, onlyExplicitlyIncluded = true)
public final class ByteArray implements Comparable {
private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();
private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder();
private static final Base64.Encoder BASE64URL_ENCODER = Base64.getUrlEncoder().withoutPadding();
private static final Base64.Decoder BASE64URL_DECODER = Base64.getUrlDecoder();
@NonNull private final byte[] bytes;
@JsonValue @NonNull private final String base64url;
/** Create a new instance by copying the contents of bytes
. */
public ByteArray(@NonNull byte[] bytes) {
this.bytes = BinaryUtil.copy(bytes);
this.base64url = BASE64URL_ENCODER.encodeToString(this.bytes);
}
private ByteArray(String base64url) throws Base64UrlException {
try {
this.bytes = BASE64URL_DECODER.decode(base64url);
} catch (IllegalArgumentException e) {
throw new Base64UrlException("Invalid Base64Url encoding: " + base64url, e);
}
this.base64url = base64url;
}
/** Create a new instance by decoding base64
as classic Base64 data. */
public static ByteArray fromBase64(@NonNull final String base64) {
return new ByteArray(BASE64_DECODER.decode(base64));
}
/**
* Create a new instance by decoding base64url
as Base64Url data.
*
* @throws Base64UrlException if base64url
is not valid Base64Url data.
*/
@JsonCreator
public static ByteArray fromBase64Url(@NonNull final String base64url) throws Base64UrlException {
return new ByteArray(base64url.split("=")[0]);
}
/**
* Create a new instance by decoding hex
as hexadecimal data.
*
* @throws HexException if hex
is not valid hexadecimal data.
*/
public static ByteArray fromHex(@NonNull final String hex) throws HexException {
try {
return new ByteArray(BinaryUtil.fromHex(hex));
} catch (Exception e) {
throw new HexException("Invalid hexadecimal encoding: " + hex, e);
}
}
/**
* @return a new instance containing a copy of this instance followed by a copy of tail
*
.
*/
public ByteArray concat(@NonNull ByteArray tail) {
return new ByteArray(Bytes.concat(this.bytes, tail.bytes));
}
public boolean isEmpty() {
return size() == 0;
}
public int size() {
return this.bytes.length;
}
/**
* @return a copy of the raw byte contents.
*/
public byte[] getBytes() {
return BinaryUtil.copy(bytes);
}
/**
* @return the content bytes encoded as classic Base64 data.
*/
public String getBase64() {
return BASE64_ENCODER.encodeToString(bytes);
}
/**
* @return the content bytes encoded as Base64Url data, without padding.
*/
public String getBase64Url() {
return base64url;
}
/**
* @return the content bytes encoded as hexadecimal data.
*/
@ToString.Include
public String getHex() {
return BinaryUtil.toHex(bytes);
}
@Override
public int compareTo(ByteArray other) {
if (bytes.length != other.bytes.length) {
return bytes.length - other.bytes.length;
}
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] != other.bytes[i]) {
return bytes[i] - other.bytes[i];
}
}
return 0;
}
}