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

org.xipki.security.util.KeyUtil Maven / Gradle / Ivy

/*
 *
 * Copyright (c) 2013 - 2020 Lijun Liao
 *
 * 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.xipki.security.util;

import static org.xipki.util.Args.notBlank;
import static org.xipki.util.Args.notNull;

import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DSAParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import org.bouncycastle.crypto.params.Ed448PublicKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.params.X25519PublicKeyParameters;
import org.bouncycastle.crypto.params.X448PublicKeyParameters;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.jcajce.interfaces.EdDSAKey;
import org.bouncycastle.jcajce.interfaces.XDHKey;
import org.bouncycastle.jcajce.provider.asymmetric.dsa.DSAUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.encoders.Hex;
import org.xipki.security.EdECConstants;
import org.xipki.util.CompareUtil;

/**
 * Key utility class.
 *
 * @author Lijun Liao
 * @since 2.0.0
 */

public class KeyUtil {

  private static final byte[]  x25519Prefix = Hex.decode("302a300506032b656e032100");
  private static final byte[] Ed25519Prefix = Hex.decode("302a300506032b6570032100");
  private static final byte[]    x448Prefix = Hex.decode("3042300506032b656f033900");
  private static final byte[]   Ed448Prefix = Hex.decode("3043300506032b6571033a00");

  private static final Map KEY_FACTORIES = new HashMap<>();

  private static final Map KEYPAIR_GENERATORS = new HashMap<>();

  private KeyUtil() {
  }

  public static KeyStore getKeyStore(String storeType)
      throws KeyStoreException {
    notBlank(storeType, "storeType");
    if ("JCEKS".equalsIgnoreCase(storeType)) {
      return KeyStore.getInstance(storeType);
    } else {
      try {
        return KeyStore.getInstance(storeType, "BC");
      } catch (KeyStoreException | NoSuchProviderException ex) {
        return KeyStore.getInstance(storeType);
      }
    }
  }

  // CHECKSTYLE:SKIP
  public static KeyPair generateRSAKeypair(int keysize, BigInteger publicExponent,
      SecureRandom random)
          throws NoSuchAlgorithmException, NoSuchProviderException,
      InvalidAlgorithmParameterException {
    BigInteger tmpPublicExponent = publicExponent;
    if (tmpPublicExponent == null) {
      tmpPublicExponent = RSAKeyGenParameterSpec.F4;
    }
    AlgorithmParameterSpec params = new RSAKeyGenParameterSpec(keysize, tmpPublicExponent);
    KeyPairGenerator kpGen = getKeyPairGenerator("RSA");
    synchronized (kpGen) {
      if (random == null) {
        kpGen.initialize(params);
      } else {
        kpGen.initialize(params, random);
      }
      return kpGen.generateKeyPair();
    }
  }

  // CHECKSTYLE:SKIP
  public static KeyPair generateDSAKeypair(int plength, int qlength, SecureRandom random)
      throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
    DSAParameterSpec dsaParamSpec = DSAParameterCache.getDSAParameterSpec(plength, qlength,
        random);
    KeyPairGenerator kpGen = getKeyPairGenerator("DSA");
    synchronized (kpGen) {
      kpGen.initialize(dsaParamSpec, random);
      return kpGen.generateKeyPair();
    }
  }

  // CHECKSTYLE:SKIP
  public static KeyPair generateDSAKeypair(DSAParameters dsaParams, SecureRandom random)
      throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
    DSAParameterSpec dsaParamSpec = new DSAParameterSpec(dsaParams.getP(), dsaParams.getQ(),
        dsaParams.getG());
    return generateDSAKeypair(dsaParamSpec, random);
  }

  // CHECKSTYLE:SKIP
  public static KeyPair generateDSAKeypair(DSAParameterSpec dsaParamSpec, SecureRandom random)
      throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
    KeyPairGenerator kpGen = getKeyPairGenerator("DSA");
    synchronized (kpGen) {
      kpGen.initialize(dsaParamSpec, random);
      return kpGen.generateKeyPair();
    }
  }

  // CHECKSTYLE:SKIP
  public static DSAPublicKey generateDSAPublicKey(DSAPublicKeySpec keySpec)
      throws InvalidKeySpecException {
    notNull(keySpec, "keySpec");
    KeyFactory kf = getKeyFactory("DSA");
    synchronized (kf) {
      return (DSAPublicKey) kf.generatePublic(keySpec);
    }
  }

  // CHECKSTYLE:SKIP
  public static KeyPair generateEdECKeypair(ASN1ObjectIdentifier curveId, SecureRandom random)
      throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
    notNull(curveId, "curveId");
    String algorithm = EdECConstants.getName(curveId);
    KeyPairGenerator kpGen = getKeyPairGenerator(algorithm);
    synchronized (kpGen) {
      if (random != null) {
        kpGen.initialize(EdECConstants.getKeyBitSize(curveId), random);
      }
      return kpGen.generateKeyPair();
    }
  }

  // CHECKSTYLE:SKIP
  public static KeyPair generateECKeypair(ASN1ObjectIdentifier curveId, SecureRandom random)
      throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
    notNull(curveId, "curveId");

    ECGenParameterSpec spec = new ECGenParameterSpec(curveId.getId());
    KeyPairGenerator kpGen = getKeyPairGenerator("EC");
    synchronized (kpGen) {
      if (random == null) {
        kpGen.initialize(spec);
      } else {
        kpGen.initialize(spec, random);
      }
      return kpGen.generateKeyPair();
    }
  }

  /**
   * Convert XDH edwards private key to EdDSA private key. As the name indicates,
   * the converted key is dummy, you cannot verify the signature signed with
   * the converted private key against the correspond public key.
   * @param key XDH private key
   * @return the corresponding EdDSA private key (dummy)
   * @throws InvalidKeySpecException
   *           If key is invalid.
   */
  // CHECKSTYLE:SKIP
  public static PrivateKey convertXDHToDummyEdDSAPrivateKey(PrivateKey key)
      throws InvalidKeySpecException {
    if (key instanceof XDHKey && key instanceof PrivateKey) {
      PrivateKeyInfo xdhPki = PrivateKeyInfo.getInstance(key.getEncoded());
      String xdhAlgo = key.getAlgorithm();

      try {
        PrivateKeyInfo edPki;
        if (xdhAlgo.equalsIgnoreCase(EdECConstants.X25519)) {
          edPki = new PrivateKeyInfo(
              new AlgorithmIdentifier(EdECConstants.id_ED25519), xdhPki.parsePrivateKey());
        } else if (xdhAlgo.equalsIgnoreCase(EdECConstants.X448)) {
          byte[] x448Octets = ASN1OctetString.getInstance(xdhPki.parsePrivateKey()).getOctets();
          byte[] ed448Octets = new byte[57];
          System.arraycopy(x448Octets, 0, ed448Octets, 0, 56);

          edPki = new PrivateKeyInfo(
              new AlgorithmIdentifier(EdECConstants.id_ED448),
              new DEROctetString(ed448Octets));
        } else {
          throw new IllegalArgumentException("unknown key algorithm " + xdhAlgo);
        }

        byte[] encoded = edPki.getEncoded();
        return getKeyFactory("EDDSA").generatePrivate(new PKCS8EncodedKeySpec(encoded));
      } catch (IOException ex) {
        throw new InvalidKeySpecException("could not convert XDH to EdDSA private key", ex);
      }
    } else {
      throw new IllegalArgumentException("key is not an XDH private key");
    }
  } // method convertXDHToDummyEdDSAPrivateKey

  private static KeyFactory getKeyFactory(String algorithm)
      throws InvalidKeySpecException {
    String alg = algorithm.toUpperCase();
    if ("ECDSA".equals(alg)) {
      alg = "EC";
    }
    synchronized (KEY_FACTORIES) {
      KeyFactory kf = KEY_FACTORIES.get(algorithm);
      if (kf != null) {
        return kf;
      }

      try {
        kf = KeyFactory.getInstance(algorithm, "BC");
      } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
        throw new InvalidKeySpecException("could not find KeyFactory for " + algorithm
            + ": " + ex.getMessage());
      }
      KEY_FACTORIES.put(algorithm, kf);
      return kf;
    }
  } // method getKeyFactory

  private static KeyPairGenerator getKeyPairGenerator(String algorithm)
      throws NoSuchAlgorithmException, NoSuchProviderException {
    String alg = algorithm.toUpperCase();
    if ("ECDSA".equals(alg)) {
      alg = "EC";
    }
    synchronized (KEYPAIR_GENERATORS) {
      KeyPairGenerator kg = KEYPAIR_GENERATORS.get(algorithm);
      if (kg != null) {
        return kg;
      }

      kg = KeyPairGenerator.getInstance(algorithm, "BC");
      KEYPAIR_GENERATORS.put(algorithm, kg);
      return kg;
    }
  } // method getKeyPairGenerator

  public static PublicKey generatePublicKey(SubjectPublicKeyInfo pkInfo)
      throws InvalidKeySpecException {
    notNull(pkInfo, "pkInfo");

    X509EncodedKeySpec keyspec;
    try {
      keyspec = new X509EncodedKeySpec(pkInfo.getEncoded());
    } catch (IOException ex) {
      throw new InvalidKeySpecException(ex.getMessage(), ex);
    }
    ASN1ObjectIdentifier aid = pkInfo.getAlgorithm().getAlgorithm();

    String algorithm;
    if (PKCSObjectIdentifiers.rsaEncryption.equals(aid)) {
      algorithm = "RSA";
    } else if (X9ObjectIdentifiers.id_dsa.equals(aid)) {
      algorithm = "DSA";
    } else if (X9ObjectIdentifiers.id_ecPublicKey.equals(aid)) {
      algorithm = "EC";
    } else {
      algorithm = EdECConstants.getName(pkInfo.getAlgorithm().getAlgorithm());
    }

    if (algorithm == null) {
      throw new InvalidKeySpecException("unsupported key algorithm: " + aid);
    }

    KeyFactory kf = getKeyFactory(algorithm);
    synchronized (kf) {
      return kf.generatePublic(keyspec);
    }
  } // method generatePublicKey

  // CHECKSTYLE:SKIP
  public static RSAPublicKey generateRSAPublicKey(RSAPublicKeySpec keySpec)
      throws InvalidKeySpecException {
    notNull(keySpec, "keySpec");
    KeyFactory kf = getKeyFactory("RSA");
    synchronized (kf) {
      return (RSAPublicKey) kf.generatePublic(keySpec);
    }
  }

  public static AsymmetricKeyParameter generatePrivateKeyParameter(PrivateKey key)
      throws InvalidKeyException {
    notNull(key, "key");

    if (key instanceof RSAPrivateCrtKey) {
      RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) key;
      return new RSAPrivateCrtKeyParameters(rsaKey.getModulus(),
        rsaKey.getPublicExponent(), rsaKey.getPrivateExponent(),
        rsaKey.getPrimeP(), rsaKey.getPrimeQ(), rsaKey.getPrimeExponentP(),
        rsaKey.getPrimeExponentQ(), rsaKey.getCrtCoefficient());
    } else if (key instanceof RSAPrivateKey) {
      RSAPrivateKey rsaKey = (RSAPrivateKey) key;
      return new RSAKeyParameters(true, rsaKey.getModulus(), rsaKey.getPrivateExponent());
    } else if (key instanceof ECPrivateKey) {
      return ECUtil.generatePrivateKeyParameter(key);
    } else if (key instanceof DSAPrivateKey) {
      return DSAUtil.generatePrivateKeyParameter(key);
    } else if (key instanceof XDHKey || key instanceof EdDSAKey) {
      try {
        return PrivateKeyFactory.createKey(key.getEncoded());
      } catch (IOException ex) {
        throw new InvalidKeyException("exception creating key: " + ex.getMessage(), ex);
      }
    } else {
      throw new InvalidKeyException("unknown key " + key.getClass().getName());
    }
  } // method generatePrivateKeyParameter

  public static AsymmetricKeyParameter generatePublicKeyParameter(PublicKey key)
      throws InvalidKeyException {
    notNull(key, "key");

    if (key instanceof RSAPublicKey) {
      RSAPublicKey rsaKey = (RSAPublicKey) key;
      return new RSAKeyParameters(false, rsaKey.getModulus(), rsaKey.getPublicExponent());
    } else if (key instanceof ECPublicKey) {
      return ECUtil.generatePublicKeyParameter(key);
    } else if (key instanceof DSAPublicKey) {
      return DSAUtil.generatePublicKeyParameter(key);
    } else if (key instanceof XDHKey || key instanceof EdDSAKey) {
      byte[] encoded = key.getEncoded();
      String algorithm = key.getAlgorithm().toUpperCase();
      if (EdECConstants.X25519.equals(algorithm)) {
        return new X25519PublicKeyParameters(encoded, encoded.length - 32);
      } else if (EdECConstants.ED25519.equals(algorithm)) {
        return new Ed25519PublicKeyParameters(encoded, encoded.length - 32);
      } else if (EdECConstants.X448.equals(algorithm)) {
        return new X448PublicKeyParameters(encoded, encoded.length - 56);
      } else if (EdECConstants.ED448.equals(algorithm)) {
        return new Ed448PublicKeyParameters(encoded, encoded.length - 57);
      } else {
        throw new InvalidKeyException("unknown Edwards key " + algorithm);
      }
    } else {
      throw new InvalidKeyException("unknown key " + key.getClass().getName());
    }
  } // method generatePublicKeyParameter

  public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(PublicKey publicKey)
      throws InvalidKeyException {
    notNull(publicKey, "publicKey");

    if (publicKey instanceof DSAPublicKey) {
      DSAPublicKey dsaPubKey = (DSAPublicKey) publicKey;
      ASN1EncodableVector vec = new ASN1EncodableVector();
      vec.add(new ASN1Integer(dsaPubKey.getParams().getP()));
      vec.add(new ASN1Integer(dsaPubKey.getParams().getQ()));
      vec.add(new ASN1Integer(dsaPubKey.getParams().getG()));
      ASN1Sequence dssParams = new DERSequence(vec);

      try {
        return new SubjectPublicKeyInfo(
            new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, dssParams),
            new ASN1Integer(dsaPubKey.getY()));
      } catch (IOException ex) {
        throw new InvalidKeyException(ex.getMessage(), ex);
      }
    } else if (publicKey instanceof RSAPublicKey) {
      RSAPublicKey rsaPubKey = (RSAPublicKey) publicKey;
      try {
        return new SubjectPublicKeyInfo(
            new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE),
            new org.bouncycastle.asn1.pkcs.RSAPublicKey(rsaPubKey.getModulus(),
                rsaPubKey.getPublicExponent()));
      } catch (IOException ex) {
        throw new InvalidKeyException(ex.getMessage(), ex);
      }
    } else if (publicKey instanceof ECPublicKey) {
      ECPublicKey ecPubKey = (ECPublicKey) publicKey;

      ECParameterSpec paramSpec = ecPubKey.getParams();
      ASN1ObjectIdentifier curveOid = detectCurveOid(paramSpec);
      if (curveOid == null) {
        throw new InvalidKeyException("Cannot find namedCurve of the given private key");
      }

      java.security.spec.ECPoint pointW = ecPubKey.getW();
      BigInteger wx = pointW.getAffineX();
      if (wx.signum() != 1) {
        throw new InvalidKeyException("Wx is not positive");
      }

      BigInteger wy = pointW.getAffineY();
      if (wy.signum() != 1) {
        throw new InvalidKeyException("Wy is not positive");
      }

      int keysize = (paramSpec.getOrder().bitLength() + 7) / 8;
      byte[] wxBytes = BigIntegers.asUnsignedByteArray(keysize, wx);
      byte[] wyBytes = BigIntegers.asUnsignedByteArray(keysize, wy);
      byte[] pubKey = new byte[1 + keysize * 2];
      pubKey[0] = 4; // uncompressed
      System.arraycopy(wxBytes, 0, pubKey, 1, keysize);
      System.arraycopy(wyBytes, 0, pubKey, 1 + keysize, keysize);

      AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey,
          curveOid);
      return new SubjectPublicKeyInfo(algId, pubKey);
    } else if (publicKey instanceof XDHKey || publicKey instanceof EdDSAKey) {
      String algorithm = publicKey.getAlgorithm().toUpperCase();
      byte[] encoded = publicKey.getEncoded();

      int keysize;
      byte[] prefix;
      ASN1ObjectIdentifier algOid;
      if (EdECConstants.ED25519.equals(algorithm)) {
        algOid = EdECConstants.id_ED25519;
        keysize = 32;
        prefix = Ed25519Prefix;
      } else if (EdECConstants.X25519.equals(algorithm)) {
        algOid = EdECConstants.id_X25519;
        keysize = 32;
        prefix = x25519Prefix;
      } else if (EdECConstants.ED448.equals(algorithm)) {
        algOid = EdECConstants.id_ED448;
        keysize = 57;
        prefix = Ed448Prefix;
      } else if (EdECConstants.X448.equals(algorithm)) {
        algOid = EdECConstants.id_X448;
        keysize = 56;
        prefix = x448Prefix;
      } else {
        throw new IllegalArgumentException("invalid algorithm " + algorithm);
      }

      if (encoded.length != prefix.length + keysize) {
        throw new IllegalArgumentException("invalid encoded PublicKey");
      }

      if (!CompareUtil.areEqual(encoded, 0, prefix, 0, prefix.length)) {
        throw new IllegalArgumentException("invalid encoded PublicKey");
      }

      byte[] keyData = Arrays.copyOfRange(encoded, prefix.length, prefix.length + keysize);
      AlgorithmIdentifier algId = new AlgorithmIdentifier(algOid);
      return new SubjectPublicKeyInfo(algId, keyData);
    } else {
      throw new InvalidKeyException("unknown publicKey class " + publicKey.getClass().getName());
    }
  } // method createSubjectPublicKeyInfo

  // CHECKSTYLE:SKIP
  public static ECPublicKey createECPublicKey(byte[] encodedAlgorithmIdParameters,
      byte[] encodedPoint)
          throws InvalidKeySpecException {
    notNull(encodedAlgorithmIdParameters, "encodedAlgorithmIdParameters");
    notNull(encodedPoint, "encodedPoint");

    ASN1Encodable algParams;
    if (encodedAlgorithmIdParameters[0] == 6) {
      algParams = ASN1ObjectIdentifier.getInstance(encodedAlgorithmIdParameters);
    } else {
      algParams = X962Parameters.getInstance(encodedAlgorithmIdParameters);
    }
    AlgorithmIdentifier algId = new AlgorithmIdentifier(
        X9ObjectIdentifiers.id_ecPublicKey, algParams);

    SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo(algId, encodedPoint);
    X509EncodedKeySpec keySpec;
    try {
      keySpec = new X509EncodedKeySpec(spki.getEncoded());
    } catch (IOException ex) {
      throw new InvalidKeySpecException(ex.getMessage(), ex);
    }

    KeyFactory kf;
    try {
      kf = KeyFactory.getInstance("EC", "BC");
    } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
      throw new InvalidKeySpecException(ex.getMessage(), ex);
    }
    return (ECPublicKey) kf.generatePublic(keySpec);
  } // method createECPublicKey

  public static ASN1ObjectIdentifier detectCurveOid(ECParameterSpec paramSpec) {
    org.bouncycastle.jce.spec.ECParameterSpec bcParamSpec = EC5Util.convertSpec(paramSpec);
    return ECUtil.getNamedCurveOid(bcParamSpec);
  }

  // CHECKSTYLE:SKIP
  public static byte[] getUncompressedEncodedECPoint(ECPoint point, int orderBitLength) {
    int orderByteLength = (orderBitLength + 7) / 8;
    byte[] keyData = new byte[1 + orderByteLength * 2];
    keyData[0] = 4;
    unsignedByteArrayCopy(keyData, 1, orderByteLength, point.getAffineX());
    unsignedByteArrayCopy(keyData, 1 + orderByteLength, orderByteLength, point.getAffineY());
    return keyData;
  } // method getUncompressedEncodedECPoint

  /**
   * Write the passed in value as an unsigned byte array to the {@code dest} from offset
   * {@code destPos}.
   *
   * @param value value to be converted.
   * @return a byte array without a leading zero byte if present in the signed encoding.
   */
  private static void unsignedByteArrayCopy(byte[] dest, int destPos,
      int length, BigInteger value) {
    byte[] bytes = value.toByteArray();
    if (bytes.length == length) {
      System.arraycopy(bytes, 0, dest, destPos, length);
    } else {
      int start = bytes[0] == 0 ? 1 : 0;
      int count = bytes.length - start;

      if (count > length) {
        throw new IllegalArgumentException("value cannot be expressed in " + length + " bytes");
      }

      System.arraycopy(bytes, start, dest, destPos + length - count, count);
    }
  } // method unsignedByteArrayCopy

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy