txt: ## dist_zef-raku-community-modules-OpenSSL.md
  [![Actions Status](https://github.com/raku-community-modules/OpenSSL/actions/workflows/linux.yml/badge.svg)](https://github.com/raku-community-modules/OpenSSL/actions) [![Actions Status](https://github.com/raku-community-modules/OpenSSL/actions/workflows/macos.yml/badge.svg)](https://github.com/raku-community-modules/OpenSSL/actions) [![Actions Status](https://github.com/raku-community-modules/OpenSSL/actions/workflows/windows.yml/badge.svg)](https://github.com/raku-community-modules/OpenSSL/actions)
  
  # NAME
  
  OpenSSL - OpenSSL bindings
  
  # SYNOPSIS
  
  ```
  use OpenSSL;
  my $openssl = OpenSSL.new;
  $openssl.set-fd(123);
  $openssl.write("GET / HTTP/1.1\r\nHost: somehost\r\n\r\n");
  
  ```
  
  # DESCRIPTION
  
  A module which provides OpenSSL bindings, making us able to set up a TLS/SSL connection.
  
  # METHODS
  
  ## method new
  
  ```
  method new(Bool :$client = False, Int :$version?)
  
  ```
  
  A constructor. Initializes OpenSSL library, sets method and context. If $version is not specified, the highest possible version is negotiated.
  
  ## method set-fd
  
  ```
  method set-fd(OpenSSL:, int32 $fd)
  
  ```
  
  Assigns connection's file descriptor (file handle) $fd to the SSL object.
  
  To get the $fd we should use C to set up the connection. (See <NativeCall>) I hope we will be able to use Raku's IO::Socket module instead of connecting through C soon-ish.
  
  ## method set-connect-state
  
  ```
  method set-connect-state(OpenSSL:)
  
  ```
  
  Sets SSL object to connect (client) state.
  
  Use it when you want to connect to SSL servers.
  
  ## method set-accept-state
  
  ```
  method set-accept-state(OpenSSL:)
  
  ```
  
  Sets SSL object to accept (server) state.
  
  Use it when you want to provide an SSL server.
  
  ## method connect
  
  ```
  method connect(OpenSSL:)
  
  ```
  
  Connects to the server using $fd (passed using .set-fd).
  
  Does all the SSL stuff like handshaking.
  
  ## method accept
  
  ```
  method accept(OpenSSL:)
  
  ```
  
  Accepts new client connection.
  
  Does all the SSL stuff like handshaking.
  
  ## method write
  
  ```
  method write(OpenSSL:, Str $s)
  
  ```
  
  Sends $s to the other side (server/client).
  
  ## method read
  
  ```
  method read(OpenSSL:, Int $n, Bool :$bin)
  
  ```
  
  Reads $n bytes from the other side (server/client).
  
  Bool :$bin if we want it to return Buf instead of Str.
  
  ## method use-certificate-file
  
  ```
  method use-certificate-file(OpenSSL:, Str $file)
  
  ```
  
  Assings a certificate (from file) to the SSL object.
  
  ## method use-privatekey-file
  
  ```
  method use-privatekey-file(OpenSSL:, Str $file)
  
  ```
  
  Assings a private key (from file) to the SSL object.
  
  ## method check-private-key
  
  ```
  method check-private-key(OpenSSL:)
  
  ```
  
  Checks if private key is valid.
  
  ## method shutdown
  
  ```
  method shutdown(OpenSSL:)
  
  ```
  
  Turns off the connection.
  
  ## method ctx-free
  
  ```
  method ctx-free(OpenSSL:)
  
  ```
  
  Frees C's SSL\_CTX struct.
  
  ## method ssl-free
  
  ```
  method ssl-free(OpenSSL:)
  
  ```
  
  Frees C's SSL struct.
  
  ## method close
  
  ```
  method close(OpenSSL:)
  
  ```
  
  Closes the connection.
  
  Unlike .shutdown it calls ssl-free, ctx-free, and then it shutdowns.
  
  # TOOLS
  
  Public key signing tools.
  
  ## OpenSSL::RSATools
  
  ```
  use OpenSSL::RSATools;
  
  my $pem = slurp 'key.pem';
  my $rsa = OpenSSL::RSAKey.new(private-pem => $pem);
  my $data = 'as df jk l';
  my $signature = $rsa.sign($data.encode);
  my $rsa = OpenSSL::RSAKey.new(public-pem => $public);
  if $rsa.verify($data.encode, $signature) { ... }
  
  ```
  
  ## OpenSSL::CryptTools
  
  Symmetric encryption tools (currently only AES256/192/128 encrypt/decrypt)
  
  ```
  use OpenSSL::CryptTools;
  
  my $ciphertext = encrypt("asdf".encode,
                           :aes256,
                           :iv(("0" x 16).encode),
                           :key(('x' x 32).encode));
  my $plaintext = decrypt($ciphertext,
                          :aes256,
                          :iv(("0" x 16).encode),
                          :key(('x' x 32).encode));
  
  ```
  
  ## OpenSSL::Digest
  
  Digest Functions (currently only md5/sha1/sha256/sha384/sha512)
  
  ```
  use OpenSSL::Digest;
  my Blob $digest = md5("xyz".encode);
  
  ```
  
  ## OpenSSL::Digest::MD5
  
  OO-Interface supporting incremental digesting
  
  ```
  use OpenSSL::Digest::MD5;
  
  my $md5 = OpenSSL::Digest::MD5.new; # Create fresh object
  $md5.add('abc');                    # pass in Str or Blob
  $md5.add('def');                    # Add some more data
  my $digest = $md5.hash;             # Blob hash (and reset)
  $md5.addfile('myfile');             # Read a file
  my $hexdigest = $md5.hex;           # hex hash  (and reset)
  
  ```
  
  # CAVEATS
  
  ## MacOS
  
  Many native libraries on MacOS are installed with the `brew` command line interface. For this module one would typically have to do a `brew install openssl`.
  
  The use of native libraries is slightly more complicated on the MacOS operating system than on other operating systems. This generally means that a symlink needs to be installed in a trusted filesystem location. If the [`MacOS::NativeLib`](https://raku.land/zef:lizmat/MacOS::NativeLib) distribution is installed, then these symlinks will be automatically created when this module is built.
  
  # SEE ALSO
  
  IO::Socket::SSL
  
  # AUTHOR
  
  * Filip Sergot
  
  Source can be located at: <https://github.com/raku-community-modules/OpenSSL> . Comments and Pull Requests are welcome.
  
  # COPYRIGHT AND LICENSE
  
  Copyright 2014 - 2022 Filip Sergot
  
  Copyright 2023 - 2025 The Raku Community
  
  This library is free software; you can redistribute it and/or modify it under the MIT License.
  