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

io.jsonwebtoken.impl.security.FieldElementConverter Maven / Gradle / Ivy

/*
 * Copyright © 2024 jsonwebtoken.io
 *
 * 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 io.jsonwebtoken.impl.security;

import io.jsonwebtoken.impl.io.Codec;
import io.jsonwebtoken.impl.lang.Bytes;
import io.jsonwebtoken.impl.lang.Converter;
import io.jsonwebtoken.impl.lang.Converters;

import java.math.BigInteger;

/**
 * Hotfix for JJWT Issue 901. This is currently hard-coded
 * expecting field elements for NIST P-256, P-384, or P-521 curves.  Ideally this should be refactored to work for
 * any curve based on its field size, not just for these NIST curves.  However, the
 * {@link EcPublicJwkFactory} and {@link EcPrivateJwkFactory} implementations only work with JWA NIST curves,
 * so this implementation is acceptable until (and if) different Weierstrass elliptic curves (ever) need to be
 * supported.
 *
 * @since 0.12.4
 */
final class FieldElementConverter implements Converter {

    static final FieldElementConverter INSTANCE = new FieldElementConverter();

    static final Converter B64URL_CONVERTER = Converters.forEncoded(BigInteger.class,
            Converters.compound(INSTANCE, Codec.BASE64URL));

    private static int bytelen(ECCurve curve) {
        return Bytes.length(curve.toParameterSpec().getCurve().getField().getFieldSize());
    }

    private static final int P256_BYTE_LEN = bytelen(ECCurve.P256);
    private static final int P384_BYTE_LEN = bytelen(ECCurve.P384);
    private static final int P521_BYTE_LEN = bytelen(ECCurve.P521);

    @Override
    public byte[] applyTo(BigInteger bigInteger) {
        byte[] bytes = Converters.BIGINT_UBYTES.applyTo(bigInteger);
        int len = bytes.length;
        if (len == P256_BYTE_LEN || len == P384_BYTE_LEN || len == P521_BYTE_LEN) return bytes;
        if (len < P256_BYTE_LEN) {
            bytes = Bytes.prepad(bytes, P256_BYTE_LEN);
        } else if (len < P384_BYTE_LEN) {
            bytes = Bytes.prepad(bytes, P384_BYTE_LEN);
        } else { // > P-384, so must be P-521:
            bytes = Bytes.prepad(bytes, P521_BYTE_LEN);
        }
        return bytes;
    }

    @Override
    public BigInteger applyFrom(byte[] bytes) {
        return Converters.BIGINT_UBYTES.applyFrom(bytes);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy