upstream: https://github.com/mirage/mirage-crypto
at main 699 lines 23 kB view raw
1(** Simpler crypto 2 3 Mirage-crypto is a cryptographic library. 4 5 The overarching API principle is simply mapping inputs to outputs, wherever 6 feasible. 7 8 Similar algorithms in the same class (like {{!Hash}hashes} or 9 {{!Cipher_block}block ciphers}) are presented as distinct modules sharing 10 the same signature. 11 12 The opam package mirage-crypto-rng provides a cryptographically secure 13 pseudo-random number generator, the package mirage-crypto-pk provides public 14 key cryptography. *) 15 16(**/**) 17 18(** A treasure-trove of random utilities. 19 20 This is largely an internal API used in related sub-libraries or tests. As 21 such, it is prone to breakage. *) 22module Uncommon : sig 23 val ( // ) : int -> int -> int 24 (** [x // y] is the ceiling division [ceil (x / y)]. 25 26 [x // y] is [0] for any non-positive [x]. 27 28 @raise Division_by_zero when [y < 1]. *) 29 30 val imin : int -> int -> int 31 32 val imax : int -> int -> int 33 (** [imax a b] returns the larger of [a] and [b]. *) 34 35 val iter2 : 'a -> 'a -> ('a -> unit) -> unit 36 (** [iter2 a b f] applies [f] to [a] then [b]. *) 37 38 val iter3 : 'a -> 'a -> 'a -> ('a -> unit) -> unit 39 (** [iter3 a b c f] applies [f] to [a], [b], then [c]. *) 40 41 val xor : string -> string -> string 42 (** [xor a b] computes the bitwise XOR of [a] and [b]. *) 43 44 val unsafe_xor_into : 45 string -> src_off:int -> bytes -> dst_off:int -> int -> unit 46 (** [unsafe_xor_into src ~src_off dst ~dst_off len] XORs [len] bytes from 47 [src] at [src_off] into [dst] at [dst_off] without bounds checks. *) 48 49 val invalid_arg : ('a, Format.formatter, unit, unit, unit, 'b) format6 -> 'a 50 (** [invalid_arg fmt] raises [Invalid_argument] with a formatted message. *) 51end 52 53(**/**) 54 55(** The poly1305 message authentication code *) 56module Poly1305 : sig 57 type 'a iter = ('a -> unit) -> unit 58 59 type t 60 (** Represents a running mac computation, suitable for appending inputs. *) 61 62 val mac_size : int 63 (** [mac_size] is the size of the output. *) 64 65 val empty : key:string -> t 66 (** [empty] is the empty context with the given [key]. 67 68 @raise Invalid_argument if key is not 32 bytes. *) 69 70 val feed : t -> string -> t 71 (** [feed t msg] adds the information in [msg] to [t]. *) 72 73 val feedi : t -> string iter -> t 74 (** [feedi t iter] feeds iter into [t]. *) 75 76 val get : t -> string 77 (** [get t] is the mac corresponding to [t]. *) 78 79 val mac : key:string -> string -> string 80 (** [mac ~key msg] is the all-in-one mac computation: 81 [get (feed (empty ~key) msg)]. *) 82 83 val maci : key:string -> string iter -> string 84 (** [maci ~key iter] is the all-in-one mac computation: 85 [get (feedi (empty ~key) iter)]. *) 86 87 val mac_into : 88 key:string -> (string * int * int) list -> bytes -> dst_off:int -> unit 89 (** [mac_into ~key datas dst dst_off] computes the [mac] of [datas]. *) 90 91 (**/**) 92 93 val unsafe_mac_into : 94 key:string -> (string * int * int) list -> bytes -> dst_off:int -> unit 95 (** [unsafe_mac_into ~key datas dst dst_off] is {!mac_into} without bounds 96 checks. *) 97 98 (**/**) 99end 100 101(** {1 Symmetric-key cryptography} *) 102 103(** Authenticated encryption with associated data. 104 105 This defines a uniform interface of symmetrics cryptographic algorithms 106 which encrypt, and also protect the integrity of the data. Additional data, 107 only used for integrity protection, not encrypted and not part of the 108 ciphertext, can be passed in optionally. This prevents the same ciphertext 109 being used at a different location. See 110 {{:https://tools.ietf.org/html/rfc5116}RFC 5116} for further description. *) 111module type AEAD = sig 112 val tag_size : int 113 (** The size of the authentication tag. *) 114 115 type key 116 (** The abstract type for the key. *) 117 118 val of_secret : string -> key 119 (** [of_secret secret] constructs the encryption key corresponding to 120 [secret]. 121 122 @raise Invalid_argument if the length of [secret] is not a valid key size. 123 *) 124 125 (** {1 Authenticated encryption and decryption with inline tag} *) 126 127 val authenticate_encrypt : 128 key:key -> nonce:string -> ?adata:string -> string -> string 129 (** [authenticate_encrypt ~key ~nonce ~adata msg] encrypts [msg] with [key] 130 and [nonce], and appends an authentication tag computed over the encrypted 131 [msg], using [key], [nonce], and [adata]. 132 133 @raise Invalid_argument if [nonce] is not of the right size. *) 134 135 val authenticate_decrypt : 136 key:key -> nonce:string -> ?adata:string -> string -> string option 137 (** [authenticate_decrypt ~key ~nonce ~adata msg] splits [msg] into encrypted 138 data and authentication tag, computes the authentication tag using [key], 139 [nonce], and [adata], and decrypts the encrypted data. If the 140 authentication tags match, the decrypted data is returned. 141 142 @raise Invalid_argument if [nonce] is not of the right size. *) 143 144 (** {1 Authenticated encryption and decryption with tag provided separately} 145 *) 146 147 val authenticate_encrypt_tag : 148 key:key -> nonce:string -> ?adata:string -> string -> string * string 149 (** [authenticate_encrypt_tag ~key ~nonce ~adata msg] encrypts [msg] with 150 [key] and [nonce]. The computed authentication tag is returned separately 151 as second part of the tuple. 152 153 @raise Invalid_argument if [nonce] is not of the right size. *) 154 155 val authenticate_decrypt_tag : 156 key:key -> 157 nonce:string -> 158 ?adata:string -> 159 tag:string -> 160 string -> 161 string option 162 (** [authenticate_decrypt ~key ~nonce ~adata ~tag msg] computes the 163 authentication tag using [key], [nonce], and [adata], and decrypts the 164 encrypted data. If the authentication tags match, the decrypted data is 165 returned. 166 167 @raise Invalid_argument if [nonce] is not of the right size. *) 168 169 (** {1 Authenticated encryption and decryption into existing buffers} *) 170 171 val authenticate_encrypt_into : 172 key:key -> 173 nonce:string -> 174 ?adata:string -> 175 string -> 176 src_off:int -> 177 bytes -> 178 dst_off:int -> 179 tag_off:int -> 180 int -> 181 unit 182 (** [authenticate_encrypt_into ~key ~nonce ~adata msg ~src_off dst ~dst_off 183 ~tag_off len] encrypts [len] bytes of [msg] starting at [src_off] with 184 [key] and [nonce]. The output is put into [dst] at [dst_off], the tag into 185 [dst] at [tag_off]. 186 187 @raise Invalid_argument if [nonce] is not of the right size. 188 @raise Invalid_argument if [String.length msg - src_off < len]. 189 @raise Invalid_argument if [Bytes.length dst - dst_off < len]. 190 @raise Invalid_argument if [Bytes.length dst - tag_off < tag_size]. *) 191 192 val authenticate_decrypt_into : 193 key:key -> 194 nonce:string -> 195 ?adata:string -> 196 string -> 197 src_off:int -> 198 tag_off:int -> 199 bytes -> 200 dst_off:int -> 201 int -> 202 bool 203 (** [authenticate_decrypt_into ~key ~nonce ~adata msg ~src_off ~tag_off dst 204 ~dst_off len] computes the authentication tag using [key], [nonce], and 205 [adata], and decrypts the [len] bytes encrypted data from [msg] starting 206 at [src_off] into [dst] starting at [dst_off]. If the authentication tags 207 match, [true] is returned, and the decrypted data is in [dst]. 208 209 @raise Invalid_argument if [nonce] is not of the right size. 210 @raise Invalid_argument if [String.length msg - src_off < len]. 211 @raise Invalid_argument if [Bytes.length dst - dst_off < len]. 212 @raise Invalid_argument if [String.length msg - tag_off < tag_size]. *) 213 214 (**/**) 215 216 val unsafe_authenticate_encrypt_into : 217 key:key -> 218 nonce:string -> 219 ?adata:string -> 220 string -> 221 src_off:int -> 222 bytes -> 223 dst_off:int -> 224 tag_off:int -> 225 int -> 226 unit 227 (** [unsafe_authenticate_encrypt_into] is {!authenticate_encrypt_into}, but 228 without bounds checks. 229 230 @raise Invalid_argument if [nonce] is not of the right size. 231 232 This may cause memory issues if an invariant is violated: 233 - [String.length msg - src_off >= len]. 234 - [Bytes.length dst - dst_off >= len]. 235 - [Bytes.length dst - tag_off >= tag_size]. *) 236 237 val unsafe_authenticate_decrypt_into : 238 key:key -> 239 nonce:string -> 240 ?adata:string -> 241 string -> 242 src_off:int -> 243 tag_off:int -> 244 bytes -> 245 dst_off:int -> 246 int -> 247 bool 248 (** [unsafe_authenticate_decrypt_into] is {!authenticate_decrypt_into}, but 249 without bounds checks. 250 251 @raise Invalid_argument if [nonce] is not of the right size. 252 253 This may cause memory issues if an invariant is violated: 254 - [String.length msg - src_off >= len]. 255 - [Bytes.length dst - dst_off >= len]. 256 - [String.length msg - tag_off >= tag_size]. *) 257 258 (**/**) 259end 260 261(** Block ciphers. 262 263 Each algorithm, and each mode of operation, is contained in its own separate 264 module. *) 265 266(** Module types for various block cipher modes of operation. *) 267module Block : sig 268 (** Modes of operation: *) 269 270 (** {e Electronic Codebook} "mode". *) 271 module type ECB = sig 272 type key 273 274 val of_secret : string -> key 275 (** Construct the encryption key corresponding to [secret]. 276 277 @raise Invalid_argument 278 if the length of [secret] is not in {{!key_sizes}[key_sizes]}. *) 279 280 val key_sizes : int array 281 (** Key sizes allowed with this cipher. *) 282 283 val block_size : int 284 (** The size of a single block. *) 285 286 val encrypt : key:key -> string -> string 287 (** [encrypt ~key src] encrypts [src] into a freshly allocated buffer of the 288 same size using [key]. 289 290 @raise Invalid_argument 291 if the length of [src] is not a multiple of {!block_size}. *) 292 293 val decrypt : key:key -> string -> string 294 (** [decrypt ~key src] decrypts [src] into a freshly allocated buffer of the 295 same size using [key]. 296 297 @raise Invalid_argument 298 if the length of [src] is not a multiple of {!block_size}. *) 299 300 val encrypt_into : 301 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 302 (** [encrypt_into ~key src ~src_off dst dst_off len] encrypts [len] octets 303 from [src] starting at [src_off] into [dst] starting at [dst_off]. 304 305 @raise Invalid_argument if [len] is not a multiple of {!block_size}. 306 @raise Invalid_argument 307 if [src_off < 0 || String.length src - src_off < len]. 308 @raise Invalid_argument 309 if [dst_off < 0 || Bytes.length dst - dst_off < len]. *) 310 311 val decrypt_into : 312 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 313 (** [decrypt_into ~key src ~src_off dst dst_off len] decrypts [len] octets 314 from [src] starting at [src_off] into [dst] starting at [dst_off]. 315 316 @raise Invalid_argument if [len] is not a multiple of {!block_size}. 317 @raise Invalid_argument 318 if [src_off < 0 || String.length src - src_off < len]. 319 @raise Invalid_argument 320 if [dst_off < 0 || Bytes.length dst - dst_off < len]. *) 321 322 (**/**) 323 324 val unsafe_encrypt_into : 325 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 326 (** [unsafe_encrypt_into] is {!encrypt_into}, but without bounds checks. 327 328 This may cause memory issues if an invariant is violated: 329 - [len] must be a multiple of {!block_size}, 330 - [src_off >= 0 && String.length src - src_off >= len], 331 - [dst_off >= 0 && Bytes.length dst - dst_off >= len]. *) 332 333 val unsafe_decrypt_into : 334 key:key -> string -> src_off:int -> bytes -> dst_off:int -> int -> unit 335 (** [unsafe_decrypt_into] is {!decrypt_into}, but without bounds checks. 336 337 This may cause memory issues if an invariant is violated: 338 - [len] must be a multiple of {!block_size}, 339 - [src_off >= 0 && String.length src - src_off >= len], 340 - [dst_off >= 0 && Bytes.length dst - dst_off >= len]. *) 341 342 (**/**) 343 end 344 345 (** {e Cipher-block chaining} mode. *) 346 module type CBC = sig 347 type key 348 349 val of_secret : string -> key 350 (** Construct the encryption key corresponding to [secret]. 351 352 @raise Invalid_argument 353 if the length of [secret] is not in {{!key_sizes}[key_sizes]}. *) 354 355 val key_sizes : int array 356 (** Key sizes allowed with this cipher. *) 357 358 val block_size : int 359 (** The size of a single block. *) 360 361 val encrypt : key:key -> iv:string -> string -> string 362 (** [encrypt ~key ~iv msg] is [msg] encrypted under [key], using [iv] as the 363 CBC initialization vector. 364 365 @raise Invalid_argument 366 if [iv] is not [block_size], or [msg] is not [k * block_size] long. *) 367 368 val decrypt : key:key -> iv:string -> string -> string 369 (** [decrypt ~key ~iv msg] is the inverse of [encrypt]. 370 371 @raise Invalid_argument 372 if [iv] is not [block_size], or [msg] is not [k * block_size] long. *) 373 374 val next_iv : ?off:int -> string -> iv:string -> string 375 (** [next_iv ~iv ciphertext ~off] is the first [iv] {e following} the 376 encryption that used [iv] to produce [ciphertext]. 377 378 For protocols which perform inter-message chaining, this is the [iv] for 379 the next message. 380 381 It is either [iv], when [String.length ciphertext - off = 0], or the 382 last block of [ciphertext]. Note that 383 384 {[ 385 encrypt ~iv msg1 386 || encrypt ~iv:(next_iv ~iv (encrypt ~iv msg1)) msg2 387 == encrypt ~iv (msg1 || msg2) 388 ]} 389 390 @raise Invalid_argument if the length of [iv] is not [block_size]. 391 @raise Invalid_argument 392 if the length of [ciphertext] is not a multiple of [block_size]. *) 393 394 val encrypt_into : 395 key:key -> 396 iv:string -> 397 string -> 398 src_off:int -> 399 bytes -> 400 dst_off:int -> 401 int -> 402 unit 403 (** [encrypt_into ~key ~iv src ~src_off dst dst_off len] encrypts [len] 404 octets from [src] starting at [src_off] into [dst] starting at 405 [dst_off]. 406 407 @raise Invalid_argument if the length of [iv] is not {!block_size}. 408 @raise Invalid_argument if [len] is not a multiple of {!block_size}. 409 @raise Invalid_argument 410 if [src_off < 0 || String.length src - src_off < len]. 411 @raise Invalid_argument 412 if [dst_off < 0 || Bytes.length dst - dst_off < len]. *) 413 414 val decrypt_into : 415 key:key -> 416 iv:string -> 417 string -> 418 src_off:int -> 419 bytes -> 420 dst_off:int -> 421 int -> 422 unit 423 (** [decrypt_into ~key ~iv src ~src_off dst dst_off len] decrypts [len] 424 octets from [src] starting at [src_off] into [dst] starting at 425 [dst_off]. 426 427 @raise Invalid_argument if the length of [iv] is not {!block_size}. 428 @raise Invalid_argument if [len] is not a multiple of {!block_size}. 429 @raise Invalid_argument 430 if [src_off < 0 || String.length src - src_off < len]. 431 @raise Invalid_argument 432 if [dst_off < 0 || Bytes.length dst - dst_off < len]. *) 433 434 (**/**) 435 436 val unsafe_encrypt_into : 437 key:key -> 438 iv:string -> 439 string -> 440 src_off:int -> 441 bytes -> 442 dst_off:int -> 443 int -> 444 unit 445 (** [unsafe_encrypt_into] is {!encrypt_into}, but without bounds checks. 446 447 This may casue memory issues if an invariant is violated: 448 - the length of [iv] must be {!block_size}, 449 - [len] must be a multiple of {!block_size}, 450 - [src_off >= 0 && String.length src - src_off >= len], 451 - [dst_off >= 0 && Bytes.length dst - dst_off >= len]. *) 452 453 val unsafe_decrypt_into : 454 key:key -> 455 iv:string -> 456 string -> 457 src_off:int -> 458 bytes -> 459 dst_off:int -> 460 int -> 461 unit 462 (** [unsafe_decrypt_into] is {!decrypt_into}, but without bounds checks. 463 464 This may casue memory issues if an invariant is violated: 465 - the length of [iv] must be {!block_size}, 466 - [len] must be a multiple of {!block_size}, 467 - [src_off >= 0 && String.length src - src_off >= len], 468 - [dst_off >= 0 && Bytes.length dst - dst_off >= len]. *) 469 470 val unsafe_encrypt_into_inplace : 471 key:key -> iv:string -> bytes -> dst_off:int -> int -> unit 472 (** [unsafe_encrypt_into_inplace] is {!unsafe_encrypt_into}, but assumes 473 that [dst] already contains the mesage to be encrypted. 474 475 This may casue memory issues if an invariant is violated: 476 - the length of [iv] must be {!block_size}, 477 - [len] must be a multiple of {!block_size}, 478 - [src_off >= 0 && String.length src - src_off >= len], 479 - [dst_off >= 0 && Bytes.length dst - dst_off >= len]. *) 480 481 (**/**) 482 end 483 484 (** {e Counter} mode. *) 485 module type CTR = sig 486 type key 487 488 val of_secret : string -> key 489 (** Construct the encryption key corresponding to [secret]. 490 491 @raise Invalid_argument 492 if the length of [secret] is not in {{!key_sizes}[key_sizes]}. *) 493 494 val key_sizes : int array 495 (** Key sizes allowed with this cipher. *) 496 497 val block_size : int 498 (** The size of a single block. *) 499 500 type ctr 501 502 val add_ctr : ctr -> int64 -> ctr 503 (** [add_ctr ctr n] adds [n] to [ctr]. *) 504 505 val next_ctr : ?off:int -> string -> ctr:ctr -> ctr 506 (** [next_ctr ~off msg ~ctr] is the state of the counter after encrypting or 507 decrypting [msg] at offset [off] with the counter [ctr]. 508 509 For protocols which perform inter-message chaining, this is the counter 510 for the next message. 511 512 It is computed as [C.add ctr (ceil (len msg / block_size))]. Note that 513 if [len msg1 = k * block_size], 514 515 {[ 516 encrypt ~ctr msg1 517 || encrypt ~ctr:(next_ctr ~ctr msg1) msg2 518 == encrypt ~ctr (msg1 || msg2) 519 ]} *) 520 521 val ctr_of_octets : string -> ctr 522 (** [ctr_of_octets buf] converts the value of [buf] into a counter. *) 523 524 val stream : key:key -> ctr:ctr -> int -> string 525 (** [stream ~key ~ctr n] is the raw keystream. 526 527 Keystream is the concatenation of successive encrypted counter states. 528 If [E(x)] is the single block [x] encrypted under [key], then keystream 529 is the first [n] bytes of 530 [E(ctr) || E(add ctr 1) || E(add ctr 2) || ...]. 531 532 Note that 533 534 {[ 535 stream ~key ~ctr (k * block_size) 536 || stream ~key ~ctr:(add ctr k) x 537 == stream ~key ~ctr ((k * block_size) + x) 538 ]} 539 540 In other words, it is possible to restart a keystream at [block_size] 541 boundaries by manipulating the counter. *) 542 543 val encrypt : key:key -> ctr:ctr -> string -> string 544 (** [encrypt ~key ~ctr msg] is [stream ~key ~ctr (len msg) lxor msg]. *) 545 546 val decrypt : key:key -> ctr:ctr -> string -> string 547 (** [decrypt] is [encrypt]. *) 548 549 val stream_into : key:key -> ctr:ctr -> bytes -> off:int -> int -> unit 550 (** [stream_into ~key ~ctr dst ~off len] is the raw key stream put into 551 [dst] starting at [off]. 552 553 @raise Invalid_argument if [Bytes.length dst - off < len]. *) 554 555 val encrypt_into : 556 key:key -> 557 ctr:ctr -> 558 string -> 559 src_off:int -> 560 bytes -> 561 dst_off:int -> 562 int -> 563 unit 564 (** [encrypt_into ~key ~ctr src ~src_off dst ~dst_off len] produces the key 565 stream into [dst] at [dst_off], and then xors it with [src] at 566 [src_off]. 567 568 @raise Invalid_argument 569 if [dst_off < 0 || Bytes.length dst - dst_off < len]. 570 @raise Invalid_argument 571 if [src_off < 0 || String.length src - src_off < len]. *) 572 573 val decrypt_into : 574 key:key -> 575 ctr:ctr -> 576 string -> 577 src_off:int -> 578 bytes -> 579 dst_off:int -> 580 int -> 581 unit 582 (** [decrypt_into] is {!encrypt_into}. *) 583 584 (**/**) 585 586 val unsafe_stream_into : 587 key:key -> ctr:ctr -> bytes -> off:int -> int -> unit 588 (** [unsafe_stream_into] is {!stream_into}, but without bounds checks. 589 590 This may cause memory issues if the invariant is violated: 591 - [off >= 0 && Bytes.length buf - off >= len]. *) 592 593 val unsafe_encrypt_into : 594 key:key -> 595 ctr:ctr -> 596 string -> 597 src_off:int -> 598 bytes -> 599 dst_off:int -> 600 int -> 601 unit 602 (** [unsafe_encrypt_into] is {!encrypt_into}, but without bounds checks. 603 604 This may cause memory issues if an invariant is violated: 605 - [dst_off >= 0 && Bytes.length dst - dst_off >= len], 606 - [src_off >= 0 && String.length src - src_off >= len]. *) 607 608 val unsafe_decrypt_into : 609 key:key -> 610 ctr:ctr -> 611 string -> 612 src_off:int -> 613 bytes -> 614 dst_off:int -> 615 int -> 616 unit 617 (** [unsafe_decrypt_into] is {!unsafe_encrypt_into}. *) 618 619 (**/**) 620 end 621 622 (** {e Galois/Counter Mode}. *) 623 module type GCM = sig 624 include AEAD 625 626 val key_sizes : int array 627 (** Key sizes allowed with this cipher. *) 628 629 val block_size : int 630 (** The size of a single block. *) 631 end 632 633 (** {e Counter with CBC-MAC} mode. *) 634 module type CCM16 = sig 635 include AEAD 636 637 val key_sizes : int array 638 (** Key sizes allowed with this cipher. *) 639 640 val block_size : int 641 (** The size of a single block. *) 642 end 643end 644 645module AES : sig 646 module ECB : Block.ECB 647 module CBC : Block.CBC 648 module CTR : Block.CTR with type ctr = int64 * int64 649 module GCM : Block.GCM 650 module CCM16 : Block.CCM16 651end 652 653module DES : sig 654 module ECB : Block.ECB 655 module CBC : Block.CBC 656 module CTR : Block.CTR with type ctr = int64 657end 658 659val accelerated : [ `XOR | `AES | `GHASH ] list 660(** Operations using non-portable, hardware-dependent implementation in this 661 build of the library. *) 662 663(** The ChaCha20 cipher proposed by D.J. Bernstein. *) 664module Chacha20 : sig 665 include AEAD 666 667 val crypt : key:key -> nonce:string -> ?ctr:int64 -> string -> string 668 (** [crypt ~key ~nonce ~ctr data] generates a ChaCha20 key stream using the 669 [key], and [nonce]. The [ctr] defaults to 0. The generated key stream is 670 of the same length as [data], and the output is the XOR of the key stream 671 and [data]. This implements, depending on the size of the [nonce] (8 or 12 672 bytes) both the original specification (where the counter is 8 byte, same 673 as the nonce) and the IETF RFC 8439 specification (where nonce is 12 674 bytes, and counter 4 bytes). 675 676 @raise Invalid_argument 677 if invalid parameters are provided. Valid parameters are: [key] must be 678 32 bytes and [nonce] 12 bytes for the IETF mode (and counter fit into 32 679 bits), or [key] must be either 16 bytes or 32 bytes and [nonce] 8 bytes. 680 *) 681end 682 683(** General stream cipher type. *) 684module type Stream = sig 685 type key 686 type result = { message : string; key : key } 687 688 val of_secret : string -> key 689 (** [of_secret s] creates a key from the secret string [s]. *) 690 691 val encrypt : key:key -> string -> result 692 (** [encrypt ~key msg] encrypts [msg] with [key]. *) 693 694 val decrypt : key:key -> string -> result 695 (** [decrypt ~key msg] decrypts [msg] with [key]. *) 696end 697 698module ARC4 : Stream 699(** {e Alleged Rivest Cipher 4}. *)