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

scodec.bits.BitVectorCrossPlatform.scala Maven / Gradle / Ivy

/*
 * Copyright (c) 2013, Scodec
 * 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.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * 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 scodec.bits

import java.security.{
  AlgorithmParameters,
  GeneralSecurityException,
  Key,
  MessageDigest,
  SecureRandom
}
import java.util.zip.{DataFormatException, Deflater}
import javax.crypto.Cipher

private[bits] trait BitVectorCrossPlatform { self: BitVector =>

  /** Compresses this vector using ZLIB.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @param level
    *   compression level, 0-9, with 0 disabling compression and 9 being highest level of
    *   compression -- see `java.util.zip.Deflater` for details
    * @param strategy
    *   compression strategy -- see `java.util.zip.Deflater` for details
    * @param nowrap
    *   if true, ZLIB header and checksum will not be used
    * @param chunkSize
    *   buffer size, in bytes, to use when compressing
    * @group conversions
    */
  final def deflate(
      level: Int = Deflater.DEFAULT_COMPRESSION,
      strategy: Int = Deflater.DEFAULT_STRATEGY,
      nowrap: Boolean = false,
      chunkSize: Int = 4096
  ): BitVector =
    bytes.deflate(level, strategy, nowrap, chunkSize).bits

  /** Decompresses this vector using ZLIB.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @param chunkSize
    *   buffer size, in bytes, to use when compressing
    * @group conversions
    */
  final def inflate(chunkSize: Int = 4096): Either[DataFormatException, BitVector] =
    bytes.inflate(chunkSize).map(_.bits)

  /** Computes a SHA-1 digest of this bit vector.
    *
    * Exceptions thrown from the underlying JCA API are propagated.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @group crypto
    */
  final def sha1: BitVector = digest("SHA-1")

  /** Computes a SHA-256 digest of this bit vector.
    *
    * Exceptions thrown from the underlying JCA API are propagated.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @group crypto
    */
  final def sha256: BitVector = digest("SHA-256")

  /** Computes an MD5 digest of this bit vector.
    *
    * Exceptions thrown from the underlying JCA API are propagated.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @group crypto
    */
  final def md5: BitVector = digest("MD5")

  /** Computes a digest of this bit vector.
    *
    * Exceptions thrown from the underlying JCA API are propagated.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @param algorithm
    *   digest algorithm to use
    * @group crypto
    */
  final def digest(algorithm: String): BitVector = digest(MessageDigest.getInstance(algorithm))

  /** Computes a digest of this bit vector.
    *
    * Exceptions thrown from the underlying JCA API are propagated.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @param digest
    *   digest to use
    * @group crypto
    */
  final def digest(digest: MessageDigest): BitVector = BitVector(bytes.digest(digest))

  /** Encrypts this bit vector using the specified cipher and key.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @param ci
    *   cipher to use for encryption
    * @param key
    *   key to encrypt with
    * @param aparams
    *   optional algorithm paramaters used for encryption (e.g., initialization vector)
    * @param sr
    *   secure random
    * @group crypto
    */
  final def encrypt(ci: Cipher, key: Key, aparams: Option[AlgorithmParameters] = None)(implicit
      sr: SecureRandom
  ): Either[GeneralSecurityException, BitVector] =
    cipher(ci, key, Cipher.ENCRYPT_MODE, aparams)(sr)

  /** Decrypts this bit vector using the specified cipher and key.
    *
    * The last byte is zero padded if the size is not evenly divisible by 8.
    *
    * @param ci
    *   cipher to use for decryption
    * @param key
    *   key to decrypt with
    * @param aparams
    *   optional algorithm paramaters used for decryption (e.g., initialization vector)
    * @param sr
    *   secure random
    * @group crypto
    */
  final def decrypt(ci: Cipher, key: Key, aparams: Option[AlgorithmParameters] = None)(implicit
      sr: SecureRandom
  ): Either[GeneralSecurityException, BitVector] =
    cipher(ci, key, Cipher.DECRYPT_MODE, aparams)(sr)

  private[bits] def cipher(
      ci: Cipher,
      key: Key,
      opmode: Int,
      aparams: Option[AlgorithmParameters] = None
  )(implicit sr: SecureRandom): Either[GeneralSecurityException, BitVector] =
    bytes.cipher(ci, key, opmode, aparams)(sr).map(_.bits)

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy