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

io.fusionauth.jwt.ec.ECDSASignature Maven / Gradle / Ivy

/*
 * Copyright (c) 2018-2019, FusionAuth, All Rights Reserved
 *
 * 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.fusionauth.jwt.ec;

import io.fusionauth.der.DerInputStream;
import io.fusionauth.der.DerOutputStream;
import io.fusionauth.der.DerValue;
import io.fusionauth.der.Tag;
import io.fusionauth.jwt.domain.Algorithm;

import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;

/**
 * Handle encoding and decoding an ECDSA signature.
 * 

* The DER encoded ECDSA signature structure is as follows: *

 *                                                                          s byte array
 *                                                                                   |
 *                                                        Length of s byte array     |
 *                                                                             |     |
 *                                                          Integer Tag        |     |
 *                        Sequence Tag                                |        |     |
 *                                  |                                 |        |     |
 * DER Encoded ECDSA Signature:  | 0x30 | lenZ | 0x02 | len(r) | r | 0x02 | len(s) | s
 *                                          |      |       |     |
 *         Length of the remaining byte array      |       |     |
 *                                                 |       |     |
 *                                        Integer Tag      |     |
 *                                                         |     |
 *                                     Length of r byte array    |
 *                                                               |
 * 
* * @author Daniel DeGroff */ public class ECDSASignature { private final byte[] bytes; public ECDSASignature(byte[] bytes) { this.bytes = bytes; } /** * Accept a DER encoded signature and extract the 'r' and the 's' components of the Elliptic signature. * * @param algorithm the signature algorithm used * @return a byte array containing the 'r' and the 's' elliptic signature components. * @throws IOException when $%@! gets real. */ public byte[] derDecode(Algorithm algorithm) throws IOException { // Incoming DER Sequence [ r, s ] DerValue[] sequence = new DerInputStream(bytes).getSequence(); byte[] r = sequence[0].getPositiveBigInteger().toByteArray(); byte[] s = sequence[1].getPositiveBigInteger().toByteArray(); byte[] result; switch (algorithm) { case ES256: result = new byte[64]; break; case ES384: result = new byte[96]; break; case ES512: result = new byte[132]; break; default: throw new IllegalArgumentException("Unable to decode the signature for algorithm [" + algorithm.name() + "]"); } int len = result.length / 2; //noinspection ManualMinMaxCalculation System.arraycopy(r, r.length > len ? 1 : 0, result, r.length < len ? 1 : 0, r.length > len ? len : r.length); //noinspection ManualMinMaxCalculation System.arraycopy(s, s.length > len ? 1 : 0, result, s.length < len ? (len + 1) : len, s.length > len ? len : s.length); return result; } /** * Accept an ECDSA encoded signature of the 'r' and 's' elliptic components, return these values DER encoded. * * @return a DER encoded sequence containing the 'r' and the 's' elliptic signature components * @throws IOException when $%@! gets real. */ public byte[] derEncode() throws IOException { // Split the ECDSA encoded signature into two parts, the r and s components byte[] r = Arrays.copyOfRange(bytes, 0, bytes.length / 2); byte[] s = Arrays.copyOfRange(bytes, bytes.length / 2, bytes.length); return new DerOutputStream() // DER Sequence [ r, s ] .writeValue(new DerValue(Tag.Sequence, new DerOutputStream() .writeValue(new DerValue(new BigInteger(1, r))) .writeValue(new DerValue(new BigInteger(1, s))))) .toByteArray(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy