# The Industria Libraries Manual

Next: , Up: (dir)

## Industria

This manual is for the Industria libraries, a collection of R6RS Scheme libraries.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Next: , Previous: Top, Up: Top

## 1 Getting started

Next: , Up: Getting started

### 1.1 Installation

The short version: extend your Scheme library search path to include the industria directory, e.g. if you're using Ikarus on a Unix system and you unpacked Industria in your home directory:

export IKARUS_LIBRARY_PATH=$HOME/industria  Other possible environment variables include CHEZSCHEMELIBDIRS, LARCENY_LIBPATH, MOSH_LOADPATH and YPSILON_SITELIB. For more details please refer to your Scheme implementation's documentation. An alternative is to move or symlink the weinholt directory into a directory that already exists in your Scheme's search path. Releases are available at https://weinholt.se/industria/. The development version of Industria is available in a Git repository. You can download the development version like this: git clone http://weinholt.se/git/industria.git/  Development snapshots are available at http://weinholt.se/gitweb/. You will also need a number of SRFI libraries. If your Scheme does not come with a collection of SRFIs already you can get them from the Scheme Libraries Team at Launchpad. Another way to install the libraries is to use the Dorodango package manager. It's available at http://home.gna.org/dorodango/. Next: , Previous: Installation, Up: Getting started ### 1.2 Usage I'll assume you're familiar with Scheme already. To load an R6RS library into your program or library, put it in the import specification. Here's Hello World for R6RS Scheme:  #!/usr/bin/env scheme-script (import (rnrs)) (display "Hello World!\n")  The first line is useful on Unix systems, but it is specified in the R6RS Non-Normative Appendices, so your Scheme might not accept programs with that line present. Common file extensions for R6RS programs are .scm, .sps, .ss or no extension at all. The (rnrs) library will normally be built-in and might not correspond to any file, but other libraries are usually found by converting the library name into a file system path. Here's an example that uses the (weinholt crypto md5) library:  (import (rnrs) (weinholt crypto md5)) (display (md5->string (md5 (string->utf8 (cadr (command-line)))))) (newline)  The md5->string and md5 bindings were imported from weinholt/crypto/md5.sls. Here is how you might run the program with Ikarus: $ ikarus --r6rs-script example.sps "a grand scheme"
A6FD66F0888EDCAC812D441EFE95E6C1


Previous: Usage, Up: Getting started

### 1.3 Conflicting names

In some places the same name is exported by two libraries, even though they have different bindings. Two disassemblers might both export a get-instruction procedure. In this case it is useful to use prefix when importing the libraries, like this:

     (import (rnrs)
(prefix (weinholt disassembler x86) x86:)
(prefix (weinholt disassembler arm) arm:))


Now the procedures will be called x86:get-instruction and arm:get-instruction. This method can also be useful for keeping track of which library a binding comes from. An alternative is to use rename:

     (import (rnrs)
(rename (weinholt disassembler x86)
(get-instruction x86:dis))
(rename (weinholt disassembler arm)
(get-instruction arm:dis)))


Next: , Previous: Getting started, Up: Top

## 2 Library reference

Next: , Up: Library reference

### 2.1 Executable file format utilities

Up: binfmt

#### 2.1.1 Parsers for the Executable and Linkable Format (ELF)

The (weinholt binfmt elf) library contains parsers for the popular ELF file format used in many operating systems. The format is used for executable files, relocatable object files and shared object files. The library exports procedures that parse these files.

Many constants are also exported. The constants are described near the procedures that return them. These constants may be used to construct ELF images, but this library does not have any code for doing so.

ELF images contain three categories of data: the ELF header, programs headers and section headers. The ELF header indicates the type of file. When an ELF executable is loaded into memory the program headers are used to map from file offsets to virtual memory addresses. The section headers contain information used by various tools. The symbol table, relocation data, and everything else is stored in section headers.

The term “program header” was too cumbersome, so the shorter “segment” has been used instead. The names of the exported constants are very similar to those given in the ELF specifications. Underscores have been changed to minus signs.

Note: The library assumes that any ports given to it can handle port-position and set-port-position!.

— Procedure: is-elf-image? input-port/filename

This procedures accepts either a filename or a binary input port. Returns #t if the file or port starts with what looks like an ELF image. If it is not an ELF image #f is returned. The port is returned to its previous position.

ELF-MAGIC
This constant contains the “magic” integer used at the start of ELF images.

— Procedure: open-elf-image input-port/filename

This procedure accepts a filename or an binary input port. The ELF header at the start of the file is parsed and returned as an elf-image object.

The returned object contains the input port that was used to read the header, so that the rest of the procedures in this library do not need to take an extra port argument. All other fields contain integers.

          (import (weinholt binfmt elf))
(open-elf-image "/bin/ls")
⇒ #[elf-image #<input-port (binary) "/bin/ls">
2 1 0 0 262 1 4203856 64 106216 0 64 56 8 64 28 27]

— Procedure: make-elf-image port word-size endianness os-abi abi-version type machine version entry phoff shoff flags ehsize phentsize phnum shentsize shnum shstrndx

Contructs a new elf-image object. This procedure is normally not useful when reading ELF images. No checks are performed on the arguments.

— Procedure: elf-image? obj

Returns #t if obj is an ELF image object.

— Procedure: elf-image-port image

If image was created by open-elf-image, then this returns the port that the ELF header was read from.

— Procedure: elf-image-word-size image

Returns an integer that represents the word size of image. The order and size of fields in the ELF format vary depending on the word size, but that is all hidden by this library.

ELFCLASS32
The image is a 32-bit ELF image.
ELFCLASS64
The image is a 64-bit ELF images.

— Procedure: elf-image-endianness image

Returns an integer that represents the endianness of image. The byte order used in ELF images is the same that is used by the machine that the image is intended to run on.

ELFDATA2LSB
The image is in little endian format.
ELFDATA2MSB
The image is in big endian format.

— Procedure: elf-image-os-abi image

The Operating System ABI indicates which operating system image was created for. The returned value might be one of the ELFOSABI-* constants.

ELFOSABI-SYSV
System V. An earlier version of ELF did not include the OS ABI field at all and this value is the default.
ELFOSABI-HPUX
ELFOSABI-NETBSD
ELFOSABI-LINUX
Linux. (This does not actually seem to be used by Linux.)
ELFOSABI-SOLARIS
ELFOSABI-AIX
ELFOSABI-IRIX
ELFOSABI-FREEBSD
ELFOSABI-TRU64
ELFOSABI-MODESTO
ELFOSABI-OPENBSD
ELFOSABI-OPENVMS
ELFOSABI-NSK
ELFOSABI-AROS

— Procedure: elf-image-abi-version image

The version number of the Operating System ABI.

— Procedure: elf-image-type image

The type of the image. This might be one of the ET-* constants.

ET-NONE
No type was specified.
ET-REL
Relocatable object file.
ET-EXEC
Executable object file.
ET-DYN
Shared object file.
ET-CORE
Core dump.
ET-LOOS
Start of the environment-specific range.
ET-HIOS
End of the environment-specific range.
ET-LOPROC
Start of the processor-specific range.
ET-HIPROC
End of the processor-specific range.

— Procedure: elf-image-machine image

Most ELF images contain executable code. This field specifies which machine type (CPU architecture) is needed to run the code.

EM-NONE
No machine type was given.
EM-M32
EM-SPARC
EM-386
The Intel 80386 and all its extensions. The 64-bit extensions use EM-X86-64 instead.
EM-68K
EM-88K
EM-860
EM-MIPS
EM-MIPS-RS3-LE
EM-PARISC
EM-SPARC32PLUS
EM-PPC
EM-PPC64
EM-S390
EM-ARM
EM-SPARCV9
EM-IA-64
EM-68HC12
EM-X86-64
The AMD x86-64 architecture.
EM-68HC11

— Procedure: elf-image-version image

The ELF format version used. There is only one valid value for this field, EV-CURRENT.

EV-CURRENT
The current ELF version.

— Procedure: elf-image-entry image

The program entry point. When an operating system has loaded an ELF image (by mapping the segments into virtual memory) it needs to know which address contains the first instruction of the program.

— Procedure: elf-image-phoff image

The port position at which the first segment can be found. The name is short for “program header offset”.

— Procedure: elf-image-shoff image

The port position at which the first section header can be found.

— Procedure: elf-image-flags image

This field can contain processor-specific flags.

— Procedure: elf-image-ehsize image

The size of the ELF header in bytes.

— Procedure: elf-image-phentsize image

The size of a segment header in bytes.

— Procedure: elf-image-phnum image

The number of segment headers contained in the ELF image.

— Procedure: elf-image-shentsize image

The size of a section header in bytes.

— Procedure: elf-image-shnum image

The number of section headers contained in the ELF image.

— Procedure: elf-image-shstrndx image

This is an index into the section headers table. It indicates which of the section headers contains the names of all the section headers.

SHN-UNDEF
This is used when there is no reference to any section.

— Constant: elf-machine-names

This is an alist that contains human-readable names for all the exported EM-* constants.

Constructs a new elf-section object. These objects represent section headers and are used to refer to the contents of the file. This procedure is normally not useful when reading ELF images. No checks are performed on the arguments.

— Procedure: elf-section? obj

Returns #t if obj is an ELF section object.

— Procedure: elf-section-name section

Gives the name of section as an index into the section name table, which contains #\nul terminated strings. The section name table is located by using elf-image-shstrndx.

— Procedure: elf-section-type section

An integer representing the type of section.

SHT-NULL
SHT-PROGBITS
The section contains executable code.
SHT-SYMTAB
The section contains a symbol table.
SHT-STRTAB
The section contains a string table.
SHT-RELA
SHT-HASH
SHT-DYNAMIC
SHT-NOTE
SHT-NOBITS
SHT-REL
SHT-SHLIB
SHT-DYNSYM
The section contains a symbol table with only the symbols needed for dynamic linking.
SHT-LOOS
Start of the environment-specific range.
SHT-HIOS
End of the environment-specific range.
SHT-LOPROC
Start of the processor-specific range.
SHT-HIPROC
End of the processor-specific range.

— Procedure: elf-section-flags section

An integer representing a bitmask of flags for section.

SHF-WRITE
The section data will be writable when the program is running.
SHF-ALLOC
The section data will be mapped into memory when the program is running.
SHF-EXECINSTR
The section data contains executable instructions.
SHF-MASKOS
SHF-MASKPROC

If section is mapped into memory when the program is running this field contains the address at which it will be mapped.

— Procedure: elf-section-offset section

The port position at which the data of section can be found.

— Procedure: elf-section-size section

The length of the data of section. If the section type is not SHT-NULL then this indicates the size of the segment in the image file.

This may contain a reference to another section.

— Procedure: elf-section-info section

This may contain extra information, depending on the type of section.

This specifies the alignment requirements of the data in section.

— Procedure: elf-section-entsize section

If section contains fixed-size entries then this is used to specify the size of those entries.

Constructs a new elf-segment object. These objects represent program headers and are used to refer to the contents of the file. This procedure is normally not useful when reading ELF images. No checks are performed on the arguments.

— Procedure: elf-segment? obj

Returns #t if obj is an ELF segment object.

— Procedure: elf-segment-type segment

An integer representing the type of the segment.

PT-NULL
This segment is unused.
PT-LOAD
PT-DYNAMIC
PT-INTERP
This segment contains the name of a program that should be invoked to interpret the binary. This is most commonly the system's dynamic linker/loader.
PT-NOTE
PT-PHDR
PT-LOPROC
Start of the processor-specific range.
PT-HIPROC
End of the processor-specific range.

— Procedure: elf-segment-flags segment

An integer representing a bitmask of flags for segment.

PF-X
This segment should be mapped as executable.
PF-W
This segment should be mapped as writable.
PF-R
This segment should be mapped as readable.
PF-MASKOS
PF-MASKPROC

— Procedure: elf-segment-offset segment

The port position for the start of segment.

The virtual address at which segment will be mapped.

The physical address at which segment will be mapped, if it is relevant to the operating system loading the executable. Normally this is just the same as the virtual address.

— Procedure: elf-segment-filesz segment

The size of segment in the file.

— Procedure: elf-segment-memsz segment

The size of segment in the program memory. This can be larger than filesz when the program uses uninitialized data (bss).

— Procedure: elf-segment-align segment

The alignment requirements of segment.

— Procedure: make-elf-symbol name binding type other shndx value size

Contructs a new elf-symbol object. This procedure is normally not useful when reading ELF images. No checks are performed on the arguments.

— Procedure: elf-symbol? obj

Returns #t if obj is an ELF symbol object.

— Procedure: elf-symbol-name symbol

The name of symbol. This is given as an index into a string table. The string table is located in one of the sections of the image. Use elf-section-link on the elf-section object for the symbol table for find it. Normally you will not need to read the name yourself, if you use elf-image-symbols to read the symbol table.

— Procedure: elf-symbol-other symbol

This field is reserved and should be zero.

— Procedure: elf-symbol-shndx symbol

The index of the section that is associated with symbol. This can also be one of the special section index constants, SHN-*.

SHN-ABS
The symbol references an absolute address.
SHN-COMMON
The symbol references an address in the uninitialized data segment (bss).

— Procedure: elf-symbol-value symbol

A value or address associated with symbol. For a symbol that refers to a function, this is the address of the function.

— Procedure: elf-symbol-size symbol

The size of the data symbol refers to.

— Procedure: elf-symbol-binding symbol

An integer representing the symbol binding semantics of symbol.

STB-LOCAL
The symbol is local to the object file it is located in.
STB-GLOBAL
The symbol can be seen by all object files.
STB-WEAK
The symbol can be seen by all object files, but may be overridden.
STB-LOOS
Start of the environment-specific range.
STB-HIOS
End of the environment-specific range.
STB-LOPROC
Start of the processor-specific range.
STB-HIPROC
End of the processor-specific range.

— Procedure: elf-symbol-type symbol

An integer representing the type of object symbol refers to.

STT-NOTYPE
No particular type.
STT-OBJECT
A variable, array or some other data object.
STT-FUNC
A function or some other executable code.
STT-SECTION
A section (like the .text section).
STT-FILE
A source code file name associated with the image.
STT-LOOS
Start of the environment-specific range.
STT-HIOS
End of the environment-specific range.
STT-LOPROC
Start of the processor-specific range.
STT-HIPROC
End of the processor-specific range.

— Procedure: elf-symbol-info symbol

This is a combination of the binding and type fields of symbol. It is used in the binary encoding of symbols, but is otherwise not interesting on its own.

These are helpers for parsing ELF binaries:

— Procedure: elf-image-section-by-name image name

Searches image for the section header named name. Returns the matching elf-section object, or #f if there is no such section.

          (import (weinholt binfmt elf))
(let ((elf (open-elf-image "/bin/ls")))
(elf-image-section-by-name elf ".text"))
⇒ #[elf-section 132 1 6 4203856 9552 65240 0 0 16 0]

— Procedure: elf-image-sections image

Returns all the section headers of image as an alist mapping names to elf-section objects.

          (let ((elf (open-elf-image "/bin/ls")))
(map car (elf-image-sections elf)))
⇒
("" ".interp" ".note.ABI-tag" ".note.gnu.build-id" ".hash"
".gnu.hash" ".dynsym" ".dynstr" ".gnu.version"
".gnu.version_r" ".rela.dyn" ".rela.plt" ".init" ".plt"
".text" ".fini" ".rodata" ".eh_frame_hdr" ".eh_frame"
".ctors" ".dtors" ".jcr" ".dynamic" ".got" ".got.plt"
".data" ".bss" ".shstrtab")

— Procedure: elf-image-symbols image

Locates and parses the symbol table of image. The symbol table contains information about the locations of functions, data structures and other things. The return value is a vector of all the symbols, represented as pairs where the car is the name of the symbol and the cdr is an elf-symbol object.

Returns #f if image has no symbol table. Most executables are “stripped” of their symbol table to save space and to make debugging more difficult.

          (let ((elf (open-elf-image "/usr/lib/debug/lib/libc-2.11.2.so")))
(assoc "memcpy" (vector->list (elf-image-symbols elf))))
⇒ ("memcpy" . #[elf-symbol 78278 18 0 12 522064 1125])


Version history:

• (1 0) – Initial release.

Next: , Previous: binfmt, Up: Library reference

### 2.2 Data decompression

The libraries in this section deal with data decompression. They're currently all based around the INFLATE algorithm that decompresses data created by gzip, zip and zlib.

Next: , Up: compression

The (weinholt compression adler-32) library provides the Adler-32 checksum used in the ZLIB data format. See compression zlib.

The procedures defined are similar to those made by define-crc in crypto crc. The exported bindings are adler-32, adler-32-init, etc. Version history:

• (0 0) – Initial version

Next: , Previous: compression adler-32, Up: compression

#### 2.2.2 GZIP custom input port

The (weinholt compression gzip) library provides a custom input port for reading GZIP compressed data.

A word of warning: the current implementation uses an internal buffer that can grow big when reading specially crafted data.

The GZIP format can support multiple compression methods, but only DEFLATE'd data is supported in this library.

— Procedure: is-gzip-file? filename-or-port

Takes a filename or a binary input port and returns true if the file looks like a GZIP file. The port should have set-port-position! and port-position.

— Procedure: make-gzip-input-port binary-input-port id close-underlying-port?

Returns a new port that can be used to read decompressed GZIP data from the binary-input-port. The id is the name of the returned port.

If close-underlying-port? is true then at the end of the GZIP stream the binary-input-port will be closed.

— Procedure: open-gzip-file-input-port filename

Opens the file specified by filename and returns a binary input port that decompresses the file on-the-fly.

— Procedure: extract-gzip binary-input-port binary-output-port

Reads compressed data from binary-input-port and writes the decompressed data to binary-output-port. Returns a list of gzip headers, one for each gzip member of the file (gzip files can be concatenated).

See RFC 1952 for a full description of the following values. Updates are available at http://www.gzip.org/format.txt.

— Procedure: gzip-text? hdr

True if the uncompressed data associated with hdr is believed to be text.

— Procedure: gzip-mtime hdr

The file's modification time as an SRFI-19 date or #f is none is available.

— Procedure: gzip-extra-data hdr

An “extra field” which some systems use to encode additional file attributes. This is an unparsed bytevector.

— Procedure: gzip-filename hdr

The file's original filename as a string or #f if none is available.

— Procedure: gzip-comment hdr

A file comment as a string or #f if none is available.

— Procedure: gzip-method hdr

The symbol slowest, fastest or an integer (probably denoting a different compression setting).

— Procedure: gzip-os hdr

The id number of the operating system that created the file. It is e.g. 0 for DOS, 1 for Amiga, 2 for VMS, 3 for Unix.

Version history:

• (0 0) – Initial version.
• (1 0) – GZIP headers are returned as a record type. extract-gzip returns a list of headers.

Next: , Previous: compression gzip, Up: compression

#### 2.2.3 Decompress DEFLATE'd data

The procedures in (weinholt compression inflate) decompress DEFLATE data streams. DEFLATE is the data format used by gzip, zip and zlib. This library handles the raw data stream.

— Procedure: inflate binary-input-port binary-output-port crc-init crc-update crc-finish

Inflates a complete DEFLATE data stream. It reads compressed data from binary-input-port and writes decompressed data to binary-output-port.

The arguments crc-init, crc-update and crc-finish should have the same semantics that (weinholt crypto crc) uses, see crypto crc and compression adler-32.

Three values are returned: the final CRC of the decompressed data, its length, and a bytevector with read but unused bytes from the input.

— Procedure: make-inflater binary-input-port sink window-size dictionary

Returns a procedure that, when called, decompresses a DEFLATE block from binary-input-port. The returned procedure should be called with zero arguments and returns either the symbol done, to signify the end of the DEFLATE stream, or more to indicate more blocks are (or will be) available.

For a description of the sink argument, see compression sliding-buffer.

The window-size is the size of the sliding window buffer. The most common value is 32*1024 bytes, but each DEFLATE stream has a correct value that was used when creating the stream. For zlib streams this value is specified in the header.

The dictionary is a bytevector that is prepended to the output buffer, but it is not actually copied to the output. See compression zlib.

The inflate algorithm needs some lookahead and therefore it can read a byte or two that does not belong to the inflate stream itself. Apply the symbol get-buffer to the returned procedure to recover those extra bytes as a bytevector.

Version history:

• (0 0) – Initial version
• (1 0)inflate returns three values (backwards incompatible change). The inflater procedures gain a way to return any buffered bytes.

Next: , Previous: compression inflate, Up: compression

#### 2.2.4 A circular buffer attached to a data sink

The (weinholt compression sliding-buffer) library provides a circular buffer that passes the buffered data to a sink (a sliding window).

A sink is a procedure with three arguments: a bytevector bv, an integer start and an integer count. When the sink procedure is called it should process count bytes starting at offset start of bv.

This library was written by Andreas Rottmann (and has been modified, see the source code for a history). It is used by the (weinholt compression inflate) library because the LZ77 component in INFLATE needs a way to copy data that has already been written to the output, and this data structure obviates the need to use a file for that purpose.

— Procedure: make-sliding-buffer sink size

Returns a new sliding buffer with the given sink and size. The size determines how far back in the output stream sliding-buffer-dup! can look.

— Procedure: sliding-buffer? obj

True if obj is a sliding buffer.

— Procedure: sliding-buffer-init! buffer bv

Copy initial data into the buffer so that it can be used with sliding-buffer-dup!. The sink does not receive this data.

— Procedure: sliding-buffer-drain! buffer

Sends the buffered data to to the buffer's sink.

— Procedure: sliding-buffer-read! buffer binary-input-port len

Reads len bytes from binary-input-port into the buffer.

— Procedure: sliding-buffer-put-u8! buffer u8

Copies the byte u8 into the buffer.

— Procedure: sliding-buffer-dup! buffer distance len

Duplicates len bytes from inside the output stream of buffer at distance bytes from the current end of the buffer.

Next: , Previous: compression sliding-buffer, Up: compression

#### 2.2.5 XZ custom input port

The (weinholt compression xz) library provides a custom input port for reading XZ compressed data. XZ is a wrapper format around the LZMA2 algorithm and it is becoming popular as a gzip/bzip2 replacement.

Note: An XZ file can specify several types of filters, other than LZMA2, but these have currently not been implemented.

The LZMA2 algorithm uses a sliding buffer that may be up to 4 gigabytes. This might cause problems when reading XZ files.

— Procedure: is-xz-file? filename-or-port

Takes a filename or a binary input port and returns true if the file looks like a XZ file. The port should have set-port-position! and port-position.

— Procedure: make-xz-input-port binary-input-port id close-underlying-port?

Returns a new port that can be used to read decompressed XZ data from the binary-input-port. The id is the name of the returned port.

To verify that the file was decompressed correctly it is necessary to close the port. On close the port will read all remaining data and compare its checksum to the checksum at the end of the file.

If close-underlying-port? is true then when the XZ input port is closed the binary-input-port will also be closed.

— Procedure: open-xz-file-input-port filename

Opens the file specified by filename and returns a binary input port that decompresses the file on-the-fly.

Version history:

• (1 0) – Initial version.

Next: , Previous: compression xz, Up: compression

The (weinholt compression zip) library provides procedures for reading and writing ZIP archives.

This library exports bindings that aren't easily identified as having to do with ZIP archives, so I suggest you use a prefix as described in Conflicting names.

The (weinholt compression zip extra) library is used to set and retrieve file attributes, look for absolute/relative path attacks, create directories, and handle system-specific file types. None of this can really be done portably, so the default version of that library does the minimum possible. A few implementation-dependent overrides are included which allow directories to be created and handle some attributes.

To learn about the file format, see http://www.info-zip.org/doc/. In brief: each file has a file record (followed by the file data), and the archive ends with a list of central directory records and a special end of central directory record. Some information is duplicated in the file and central directory records.

— Procedure: get-central-directory binary-input-port

Returns the central directory of the ZIP archive in binary-input-port. This is a list of central directory records and the end of central directory record.

— Procedure: central-directory->file-record zip-port cdir

Uses the data in the central directory record cdir to read the associated file record from zip-input-port. The returned value is also referred to as a local file header.

— Procedure: extract-file zip-port local central

Extracts the file associated with the local and central records. The zip-port is the same port the records were read from.

The extracted file will be created relative to the current working directory (or default filespec) and will retain as many attributes as possible from those recorded in the ZIP archive.

— Procedure: extract-to-port zip-port local central dest-port

Extracts the file associated with the local and central records to the given binary output port dest-port. The zip-port is the same port the records were read from.

It is possible to preserve the file's attributes (at least if the extracted file is a regular byte stream) by using the accessors for local and central similarly to how the “extra” library uses that data.

Creating a ZIP archive is done by appending each file, and then when done appending the central directory. The central directory is in this case a list of central directory records returned by e.g. append-file. The port the ZIP archive is written to must support port-position and set-port-position!.

Note: Currently there is no compression performed when creating archives.

— Procedure: append-file zip-port filename

Appends the file given by filename to zip-port, which is a binary output port. Returns a central directory record.

— Procedure: append-port zip-port data-port filename date local-extra central-extra os-made-by internal-attributes external-attributes

Similar to append-file, except no file is used. Instead the data for the file is read from the binary input port data-port. Because there is no file, all the file attributes need to be provided explicitly. A central directory record is returned.

For a description of the attributes, see the accessors for file and central directory records.

— Procedure: append-central-directory zip-port centrals

Writes a list of central directory records to the zip-port and then appends the special end of central directory record. After this no more data should be written to the ZIP archive. The list of central directory records centrals should be those returned by append-file and append-port.

— Procedure: create-file zip-port filenames

Builds a complete ZIP archive that includes all the files specified by the list filenames and writes it to port, which should be a binary output port.

— Procedure: supported-compression-method? n

True if n represents a supported compression method. Currently only stored and deflated are supported. See file-record-compression-method.

— Procedure: unsupported-error? obj

If an attempt was made to access an unsupported file record or to extract a file using an unsupported compression method then a condition will be raised that satisfies this predicate.

— Procedure: file-record? obj

True if obj is a file record.

— Procedure: file-record-minimum-version frec

This is the minimum supported version of the ZIP standard required to extract the file. Currently vresion 2.0 is supported (which is encoded as the exact integer 20).

— Procedure: file-record-flags frec

Various flags that can indiciate which compression option was used, etc. You can probably ignore these.

— Procedure: file-record-compression-method frec

Returns an integer that represents the compression method that was used when storing the file associated with frec. Most ZIP files use only Deflate and store.

• compression-stored means the file was stored without any compression.
• compression-shrunk is the obsolete Shrunk method.
• compression-reduced1 is the obsolete Reduced method with factor 1.
• compression-reduced2 same as above, factor 2.
• compression-reduced3 same as above, factor 3.
• compression-reduced4 same as above, factor 4.
• compression-imploded is the obsolete Implode method.
• compression-deflated is the Deflate compression algorithm.
• compression-deflate64 is a slightly modified Deflate.
• compression-pkimplode is something else.
• compression-bzip2 is BZIP2.

— Procedure: file-record-date frec

The file's modification time as an SRFI-19 date.

— Procedure: file-record-crc-32 frec

The file's CRC-32 checksum. See crypto crc.

— Procedure: file-record-compressed-size frec

The number of bytes the file uses inside the ZIP archive.

— Procedure: file-record-uncompressed-size frec

The number of bytes the file will use when it has been decompressed.

— Procedure: file-record-filename frec

The filename of the file. This might be different in the associated central directory record (e.g. due to mischief). This can also be the string "-" if the file came from the standard input port.

— Procedure: file-record-extra frec

An list of id and data pairs. This is used to encode file attributes, etc. See the file format specification for more information.

— Procedure: central-directory? obj

True if obj is a central-directory record.

This is the version of the ZIP standard supported by the implementation that created the archive.

The ID number of the operating system on which the ZIP archive was created. See the file format specification for a full list (DOS is 0, Unix is 3).

— Procedure: central-directory-minimum-version cdir

This is the minimum supported version of the ZIP standard required to extract the file. Currently version 2.0 is supported (which is encoded as the exact integer 20).

— Procedure: central-directory-flags cdir

See file-record-flags.

— Procedure: central-directory-compression-method cdir

See file-record-compression-method.

— Procedure: central-directory-date cdir

The file's modification time as an SRFI-19 date.

— Procedure: central-directory-crc-32 cdir

The file's CRC-32 checksum. See crypto crc.

— Procedure: central-directory-compressed-size cdir

The number of bytes the file uses inside the ZIP archive.

— Procedure: central-directory-uncompressed-size cdir

The number of bytes the file will use when it has been decompressed.

— Procedure: central-directory-disk-number-start cdir

The number of the split archive that the file starts on. Note that there is no explicit support for split archives, so this is untested.

— Procedure: central-directory-internal-attributes cdir

Bit 0 of this integer is set if the file is believed to be text. This might be useful for end of line conversion, but it is probably unreliable.

— Procedure: central-directory-external-attributes cdir

The file attributes of the file. The format depends on the os-made-by field.

— Procedure: central-directory-filename cdir

See file-record-filename.

— Procedure: central-directory-extra cdir

See file-record-extra. Note that some of the fields have the same ID here and in the file records, but slightly different encodings.

— Procedure: central-directory-comment cdir

A textual comment associated with the file.

— Procedure: end-of-central-directory? obj

True of obj is an end-of-central-directory record.

— Procedure: end-of-central-directory-disk edir

The number of the split archive where edir is located.

— Procedure: end-of-central-directory-start-disk edir

The number of the split archive where the central directory begins.

— Procedure: end-of-central-directory-entries edir

The number of records in the central directory in this split archive.

— Procedure: end-of-central-directory-total-entries edir

The number of records in the central directory for the whole archive.

— Procedure: end-of-central-directory-comment edir

A textual comment associated with the whole archive.

Version history:

• (0 0) – Initial version

Previous: compression zip, Up: compression

#### 2.2.7 ZLIB custom input port

The (weinholt compression zlib) library provides a custom input port for reading ZLIB compressed data.

— Procedure: make-zlib-input-port binary-input-port id max-buffer-size close-underlying-port? dictionaries

Returns a binary input port that decompresses and reads a ZLIB stream from the binary input port binary-input-port. The id is the name of the returned custom binary input port.

If max-buffer-size is false then the internal buffer can grow without bounds (might be a bad idea). Protocols using ZLIB will normally specify a "flush" behavior. If your protocol uses flushing and specifies a maximum record size, then use that size as max-buffer-size.

If close-underlying-port? is true then at the end of the zlib stream the binary-input-port will be closed.

An application can define dictionaries which can improve compression by containing byte sequences commonly found at the start of files. The dictionaries argument is an alist that maps Adler-32 checksums to bytevectors. See compression adler-32.

Version history:

• (0 0) – Initial version

Next: , Previous: compression, Up: Library reference

### 2.3 Cryptographic primitives

Beware that if you're using some of these libraries for sensitive data, let's say passwords, then there is probably no way to make sure a password is ever gone from memory. There is no guarantee that the passwords will not be swapped out to disk or transmitted by radio. There might be other problems as well. The algorithms themselves might be weak. Don't pick weak keys. Know what you're doing.

Your Scheme's implementation of (srfi :27 random-bits) might be too weak. It's common that it will be initialized from time alone, so an attacker can easily guess your random-source internal state by trying a few timestamps and checking which one generates the data you sent. These libraries try to use /dev/urandom if it exists, but if it doesn't they fall back on SRFI-27 and could reveal the secret of your heart to the enemy. See RFC4086 for details on how randomness works. And remember what the license says about warranties. Don't come crying to me if the enemy deciphers your secret messages and your whole convoy blows up. These libraries have not been validated by the NIST or the FDA and quite likely aren't allowed for government work.

Next: , Up: crypto

The (weinholt crypto aes) library provides an implementation of the symmetrical Rijndael cipher as parameterized by the Advanced Encryption Standard (AES). It was created by the Belgian cryptographers Joan Daemen and Vincent Rijmen. Key lengths of 128, 192 and 256 bits are supported.

The code uses clever lookup tables and is probably as fast as any R6RS implementation of AES can be without using an FFI. The number of modes provided is pretty sparse though (only ECB and CTR). It also leaks key material via memory.

— Procedure: expand-aes-key key

Expands the key into an AES key schedule suitable for aes-encrypt!. The key must be a bytevector of length 16, 24 or 32 bytes. The type of the return value is unspecified.

— Procedure: aes-encrypt! source source-start target target-start key-schedule

Takes the 16 bytes at source+source-start, encrypts them in Electronic Code Book (ECB) mode using the given key-schedule, and then writes the result at target+target-start. The source and the target can be the same.

          (import (weinholt crypto aes))
(let ((buf (string->utf8 "A Scheme at work"))
(sched (expand-aes-key (string->utf8 "super-secret-key"))))
(aes-encrypt! buf 0 buf 0 sched)
buf)
⇒ #vu8(116 7 242 187 114 235 130 138 166 39 24 204 117 224 5 8)


It is generally not a good idea to use ECB mode alone.

— Procedure: reverse-aes-schedule key-schedule

Reverses the key-schedule to make it suitable for aes-decrypt!.

— Procedure: aes-decrypt! source source-start target target-start key-schedule

Performs the inverse of aes-encrypt!. The key-schedule should first be reversed with reverse-aes-schedule.

          (import (weinholt crypto aes))
(let ((buf (bytevector-copy #vu8(116 7 242 187 114 235 130 138
166 39 24 204 117 224 5 8)))
(sched (reverse-aes-schedule
(expand-aes-key
(string->utf8 "super-secret-key")))))
(aes-decrypt! buf 0 buf 0 sched)
(utf8->string buf))
⇒ "A Scheme at work"

— Procedure: clear-aes-schedule! key-schedule

Clears the AES key schedule so that it no longer contains cryptographic material. Please note that there is no guarantee that the key material will actually be gone from memory. It might remain in temporary numbers or other values.

— Procedure: aes-ctr! source source-start target target-start len key-schedule ctr

Encrypts or decrypts the len bytes at source+source-start using Counter (CTR) mode and writes the result to target+target-start. The len does not need to be a block multiple. The ctr argument is a non-negative integer.

This procedure is its own inverse and the key-schedule should not be reversed for decryption.

Never encrypt more than once using the same key-schedule and ctr value. If you're not sure why that is a bad idea, you should read up on CTR mode.

— Procedure: aes-cbc-encrypt! source source-start target target-start k key-schedule iv

Encrypts k bytes in the bytevector source starting at source-start with AES in CBC mode and writes the result to target at target-start.

The argument k must be an integer multiple of 16, which is the block length.

The iv bytevector is an Initial Vector. It should be 16 bytes long, initialized to random bytes. This procedure updates the iv after processing a block.

— Procedure: aes-cbc-decrypt! source source-start target target-start k key-schedule iv

The inverse of aes-cbc-encrypt!.

Version history:

• (1 0) – Initial version.

Next: , Previous: crypto aes, Up: crypto

#### 2.3.2 ARCFOUR stream cipher

The (weinholt crypto arcfour) library provides the well-known ARCFOUR stream cipher. It is the fastest of the ciphers provided by this library collection.

Since this is a stream cipher there is no block length.

— Procedure: expand-arcfour-key key

Expands the bytevector key into an ARCFOUR keystream value. The return value has an unspecified type and is suitable for use with the other procedures exported by this library.

Never use the same key to encrypt two different plaintexts.

— Procedure: arcfour! source source-start target target-start k keystream

Reads k bytes from source starting at source-start, XORs them with bytes from the keystream, and writes them to target starting at target-start. If source and target are the same object then it is required that target-start be less then or equal to source-start.

          (import (weinholt crypto arcfour))
(let ((buf #vu8(90 60 247 233 181 200 38 52 121 82 133
98 244 159 12 97 90 157 43 183 249 170
73 244 126))
(keystream (expand-arcfour-key
(string->utf8 "hardly a secret"))))
(arcfour! buf 0 buf 0 (bytevector-length buf) keystream)
(clear-arcfour-keystream! keystream)
(utf8->string buf))
⇒ "I AM POKEY THE PENGUIN!!!"


Discards n bytes from the keystream keystream. It is recommended that the beginning of the keystream is discarded. Some protocols, e.g. RFC 4345, require it.

— Procedure: clear-arcfour-keystream! keystream

Removes all key material from the keystream.

Next: , Previous: crypto arcfour, Up: crypto

#### 2.3.3 The Blowfish Cipher

The (weinholt crypto blowfish) library is a complete implementation of Bruce Schneier's Blowfish cipher. It is a symmetric block cipher with key length between 8 and 448 bits. The key length does not affect the performance.

— Procedure: expand-blowfish-key key

Expands a Blowfish key, which is a bytevector of length between 1 and 56 bytes (the longer the better). The returned key schedule can be used with blowfish-encrypt! or reverse-blowfish-schedule.

— Procedure: blowfish-encrypt! source source-index target target-index schedule

Encrypts the eight bytes at source+source-start using Electronic Code Book (ECB) mode. The result is written to target+target-start.

— Procedure: reverse-blowfish-schedule

Reverses a Blowfish key schedule so that it can be used with blowfish-decrypt!.

— Procedure: blowfish-decrypt! source source-index target target-index schedule

The inverse of blowfish-encrypt!.

— Procedure: clear-blowfish-schedule!

Clears the Blowfish key schedule so that it no longer contains cryptographic material. Please note that there is no guarantee that the key material will actually be gone from memory. It might remain in temporary numbers or other values.

— Procedure: blowfish-cbc-encrypt! source source-start target target-start k schedule iv

Encrypts k bytes in the bytevector source starting at source-start with Blowfish in CBC mode and writes the result to target at target-start.

The argument k must be an integer multiple of 8, which is the block length.

The iv bytevector is an Initial Vector. It should be 8 bytes long, initialized to random bytes. This procedure updates the iv after processing a block.

— Procedure: blowfish-cbc-decrypt! source source-start target target-start k schedule iv

The inverse of blowfish-cbc-encrypt!.

Version history:

• (0 0) – Initial version.
• (0 1) – Added procedures for CBC mode.

Next: , Previous: crypto blowfish, Up: crypto

#### 2.3.4 Cyclic Redundancy Codes

The (weinholt crypto crc) library exports syntax for defining procedures that calculate CRCs. There is a simple syntax that simply requires the name of the CRC, and an advanced syntax that can define new CRCs.

CRCs do not really qualify as cryptography, because it is trivial to modify data so that the modified data's CRC matches the old one.

— Syntax: define-crc name

This is the simple interface that requires merely the name of the CRC algorithm. The pre-defined CRCs that can be used this way are currently: crc-32, crc-16, crc-16/ccitt, crc-32c, crc-24, crc-64 (CRC-64-ISO), and crc-64/ecma-182.

          (import (weinholt crypto crc))
(define-crc crc-32)

— Syntax: define-crc name width polynomial init ref-in ref-out xor-out check

For details on how the arguments work, and the theory behind them, see Ross N. Williams's paper A painless guide to CRC error detection algorithms, which is available at http://www.ross.net/crc/crcpaper.html. A brief description of the arguments follows.

The width is the bitwise length of the polynomial. You might be led to believe that it should sometimes be 33, but if so you've been counting the highest bit, which doesn't count.

The polynomial for CRC-16 is sometimes given as x^16 + x^15 + x^2 + 1. This translates to #b1000000000000101 (#x8005). Notice that x^16 is absent. Don't use the reversed polynomial if you have one of those, instead set ref-in and ref-out properly.

After a CRC has been calculated it is sometimes xor'd with a final value, this is xor-out.

check is either #f or the CRC of the string "123456789".

— Syntax: define-crc name (coefficients ...) init ref-in ref-out xor-out check

This is a slightly easier version of the advanced interface where you can simply specify the powers of the coefficients. CRC-16 in this syntax becomes:

          (import (weinholt crypto crc))
(define-crc crc-16 (16 15 2 0) #x0000 #t #t #x0000 #xBB3D)
==>
(begin
(define (crc-16 bv)
(crc-16-finish (crc-16-update (crc-16-init) bv)))
(define (crc-16-init) #x0000)
(define (crc-16-finish r) (bitwise-xor r #x0000))
(define (crc-16-self-test)
(if #xBB3D
(if (= (crc-16 (string->utf8 "123456789")) #xBB3D)
'success 'failure)
'no-self-test))
...)


Another example: the polynomial x^8 + x^2 + x + 1 in this syntax is (8 2 1 0).

After e.g. (define-crc crc-32) has been used, these bindings will be available (with names that match the name of the CRC):

— Procedure: crc-32 bytevector

Calculates the final CRC of the entire bytevector and returns it as an integer.

          (import (weinholt crypto crc))
(define-crc crc-32)
(crc-32 (string->utf8 "A fiendish scheme"))
⇒ 1384349758

— Procedure: crc-32-init

Returns an initial CRC state.

— Procedure: crc-32-update state bv [start end]

Uses the state and returns a new state that includes the CRC of the given bytes.

          (import (weinholt crypto crc))
(define-crc crc-32)
(crc-32-finish
(crc-32-update (crc-32-init)
(string->utf8 "A fiendish scheme")))
⇒ 1384349758

— Procedure: crc-32-finish state

Finalizes the CRC state.

— Procedure: crc-32-width

Returns the bit-width of the CRC, e.g. 32 for CRC-32.

— Procedure: crc-32-self-test

Performs a sanity check and returns either success, failure or no-self-test.

Version history:

• (1 0) – Initial version. Includes crc-32, crc-16, crc-16/ccitt, crc-32c, and crc-24.
• (1 1) – Added crc-64 and the -width procedures. The -update procedures use fixnums if (fixnum-width) is larger than the CRC's width. (1 2) – Added crc-64/ecma-182.

Next: , Previous: crypto crc, Up: crypto

#### 2.3.5 Data Encryption Standard

The Data Encryption Standard (DES) is older than AES and uses shorter keys. To get longer keys the Triple Data Encryption Algorithm (TDEA, 3DES) is commonly used instead of DES alone.

The (weinholt crypto des) library is incredibly inefficient and the API is, for no good reason, different from the AES library. You should probably use AES instead, if possible.

Returns #f if the DES key has good parity, or the index of the first bad byte. Each byte of the key has one parity bit, so even though it is a bytevector of length eight (64 bits), only 56 bits are used for encryption and decryption. Parity is usually ignored.

— Procedure: des! bv key-schedule [offset E]

The fundamental DES procedure, which performs both encryption and decryption in Electronic Code Book (ECB) mode. The eight bytes starting at offset in the bytevector bv are modified in-place.

The offset can be omitted, in which case 0 is used.

The E argument will normally be omitted. It is only used by the des-crypt procedure.

          (import (weinholt crypto des))
(let ((buf (string->utf8 "security"))
(sched (permute-key (string->utf8 "terrible"))))
(des! buf sched)
buf)
⇒ #vu8(106 72 113 111 248 178 225 208)

          (import (weinholt crypto des))
(let ((buf (bytevector-copy #vu8(106 72 113 111 248 178 225 208)))
(sched (reverse (permute-key (string->utf8 "terrible")))))
(des! buf sched)
(utf8->string buf))
⇒ "security"

— Procedure: permute-key key

Permutes the DES key into a key schedule. The key schedule is then used as an argument to des!. To decrypt, simply reverse the key schedule. The return value is a list.

— Procedure: tdea-permute-key key1 [key2 key3]

Permutes a 3DES key into a key schedule. If only one argument is given then it must be a bytevector of length 24. If three arguments are given they must all be bytevectors of length eight.

The return value's type is unspecified.

— Procedure: tdea-encipher! bv offset key

Encrypts the eight bytes at offset of bv using the given 3DES key schedule.

— Procedure: tdea-decipher! bv offset key

The inverse of tdea-encipher!.

— Procedure: tdea-cbc-encipher! bv key iv offset count

Encrypts the count bytes at offset of bv using Cipher Block Chaining (CBC) mode.

The iv argument is the Initial Vector, which is XOR'd with the data before encryption. It is a bytevector of length eight and it is modified for each block.

Both offset and count must be a multiples of eight.

— Procedure: tdea-cbc-decipher! bv key iv offset count

The inverse of tdea-cbc-encipher!.

This is a password hashing algorithm that used to be very popular on Unix systems, but is today too fast (which means brute forcing passwords from hashes is fast). The password string is at most eight characters.

The algorithm is based on 25 rounds of a slightly modified DES.

The salt must be a string of two characters from the alphabet #\A#\Z, #\a#\z, #\0#\9, #\. and #\/.

          (import (weinholt crypto des))
⇒ "4tQSEW3lEnOio"


A more general interface is also available, see crypto password.

Version history:

• (1 0) – Initial version.

Next: , Previous: crypto des, Up: crypto

#### 2.3.6 Diffie-Hellman key exchange

The (weinholt crypto dh) library exports procedures and constants for Diffie-Hellman (Merkle) key exchange. D-H works by generating a pair of numbers, sending one of them to the other party, and using the other one and the one you receive to compute a shared secret. The idea is that it's difficult for an eavesdropper to deduce the shared secret.

The D-H exchange must be protected by e.g. public key encryption because otherwise a MITM attack is trivial. It is best to use a security protocol designed by an expert.

— Procedure: make-dh-secret generator prime bit-length

Generates a Diffie-Hellman secret key pair. Returns two values: the secret key (of bitwise length bit-length) part and the public key part.

— Procedure: expt-mod base exponent modulus

Computes (mod (expt base exponent) modulus). This is modular exponentiation, so all the parameters must be integers.

The exponent can also be negative (set it to -1 to calculate the multiplicative inverse of base).

          (import (weinholt crypto dh))
(let ((g modp-group15-g) (p modp-group15-p))
(let-values (((y Y) (make-dh-secret g p 320))
((x X) (make-dh-secret g p 320)))
;; The numbers being compared are the shared secret
(= (expt-mod X y modp-group15-p)
(expt-mod Y x modp-group15-p))))
⇒ #t


This library also exports a few well known modular exponential (MODP) Diffie-Hellman groups (generators and primes) that have been defined by Internet RFCs. They are named modp-groupN-g (generator) and modp-groupN-p (prime) where N is the number of the group. Groups 1, 2, 5, 14, 15, 16, 17 and 18 are currently exported. They all have different lengths and longer primes are more secure but also slower. See RFC 3526 for more on this. Version history:

• (1 0) – Initial version.

Next: , Previous: crypto dh, Up: crypto

#### 2.3.7 Digital Signature Algorithm

The (weinholt crypto dsa) library provides procedures for creating and verifying DSA signatures. DSA is a public key signature algorithm, which means that it uses private and public key pairs. With a private key you can create a signature that can then be verified by someone using the corresponding public key. The idea is that it's very difficult to create a correct signature without having access to the private key, so if the signature can be verified it must have been made by someone who has access to the private key.

DSA is standardized by FIPS Publication 186. It is available at this web site: http://csrc.nist.gov/publications/PubsFIPS.html.

There is currently no procedure to generate a new DSA key. Here is how to generate keys with OpenSSL or GnuTLS:

openssl dsaparam 1024 | openssl gendsa /dev/stdin > dsa.pem
certtool --dsa --bits 1024 -p > dsa.pem


The key can then be loaded with dsa-private-key-from-pem-file.

— Procedure: make-dsa-public-key p q g y

Returns a DSA public key value. See the FIPS standard for a description of the parameters.

To access the fields use dsa-public-key-p, dsa-public-key-q, dsa-public-key-g and dsa-public-key-y.

— Procedure: dsa-public-key? obj

True if obj is a DSA public key value.

— Procedure: dsa-public-key-length key

Returns the number of bits in the p value of key. This is often considered to be the length of the key. The bitwise-length of q is also important, it corresponds with the length of the hashes used for signatures.

— Procedure: make-dsa-private-key p q g y x

Returns a DSA private key value. See the FIPS standard for a description of the parameters.

To access the fields use dsa-private-key-p, dsa-private-key-q, dsa-private-key-g, dsa-private-key-y and dsa-private-key-x.

— Procedure: dsa-private-key? obj

Returns #t if obj is a DSA private key.

— Procedure: dsa-private->public private-key

Converts a private DSA key into a public DSA key by removing the private fields.

— Procedure: dsa-private-key-from-bytevector bv

Parses bv as an ASN.1 DER encoded private DSA key.

— Procedure: dsa-private-key-from-pem-file filename

Opens the file and reads a private DSA key. The file should be in Privacy Enhanced Mail (PEM) format and contain an ASN.1 DER encoded private DSA key.

Encrypted keys are currently not supported.

— Procedure: dsa-signature-from-bytevector bv

Parses the bytevector bv as an ASN.1 DER encoded DSA signature. The return value is a list with the r and s values that make up a DSA signature.

— Procedure: dsa-create-signature hash private-key

The hash is the message digest (as a bytevector) of the data you want to sign. The hash and the private-key are used to create a signature which is returned as two values: r and s.

The hash can e.g. be an SHA-1 message digest. Such a digest is 160 bits and the q parameter should then be 160 bits.

— Procedure: dsa-verify-signature hash public-key r s

The hash is the message digest (as a bytevector) of the data which the signature is signing.

Returns #t if the signature matches, otherwise #f.

Version history:

• (1 0) – Initial version.

Next: , Previous: crypto dsa, Up: crypto

#### 2.3.8 Elliptic Curve Cryptography

The (weinholt crypto ec) provides algorithms and definitions for working with elliptic curves.

Only curves over prime finite fields are currently supported. Points are either +inf.0 (the point at infinity) or a pair of x and y coordinates.

Some standardized curves are exported:

secp256r1
This curve is equivalent to a 3072-bit RSA modulus.
nistp256
Curve P-256. This is the same curve as above.
secp384r1
This curve is equivalent to a 7680-bit RSA modulus.
nistp384
Curve P-384. This is the same curve as above.
secp521r1
This curve is equivalent to a 15360-bit RSA modulus. The “521” is not a typo.
nistp521
Curve P-521. This is the same curve as above.
— Procedure: make-elliptic-prime-curve p a b G n h

Constructs a new elliptic-curve object given the domain parameters of a curve:

y^2 \equiv x^3 + ax + b (mod p).

Normally one will be working with pre-defined curves, so this constructor can be safely ignored. The curve definition will include all these parameters.

— Procedure: elliptic-prime-curve? obj

Returns #t if obj is an elliptic prime curve.

The accessors can be safely ignored unless you're interested in the curves themselves.

— Procedure: elliptic-curve-a elliptic-curve

This is one of the parameters that defines the curve: an element in the field.

— Procedure: elliptic-curve-b elliptic-curve

This is one of the parameters that defines the curve: another element in the field.

— Procedure: elliptic-curve-G elliptic-curve

This is one of the parameters that defines the curve: the base point, i.e. an actual point on the curve.

— Procedure: elliptic-curve-n elliptic-curve

This is one of the parameters that defines the curve: a prime that is the order of G (the base point).

— Procedure: elliptic-curve-h elliptic-curve

This is one of the parameters that defines the curve: the cofactor.

— Procedure: elliptic-prime-curve-p elliptic-prime-curve

This is one of the parameters that defines the curve: the integer that defines the prime finite field.

— Procedure: elliptic-curve=? elliptic-curve_1 elliptic-curve_2

Returns #t if the elliptic curve objects are equal (in the sense that all domain parameters are equal).

— Procedure: ec+ P Q elliptic-curve

This adds the points P and Q, which must be points on elliptic-curve.

— Procedure: ec- P [Q] elliptic-curve

This subtracts Q from P, both of which must be points on elliptic-curve. If Q is omitted it returns the complement of P.

— Procedure: ec* multiplier P elliptic-curve

This multiplies P by multiplier. P must be a point on elliptic-curve and multiplier must be a non-negative integer.

This operation is the elliptic curve equivalence of expt-mod.

— Procedure: bytevector->elliptic-point bytevector elliptic-curve

Converts bytevector to a point on elliptic-curve. When points are sent over the network or stored in files they are first converted to bytevectors.

— Procedure: integer->elliptic-point integer elliptic-curve

Performs the same conversion as bytevector->elliptic-point, but first converts integer to a bytevector.

— Procedure: ->elliptic-point x elliptic-curve

A generic procedure that accepts as input an x that is either already a point, a bytevector representing a point, or an integer representing a point.

— Procedure: elliptic-point->bytevector point elliptic-curve

Converts point to its bytevector representation. This representation is sometimes hashed, e.g. in SSH public keys, so the canonical representation is used for compatibility with other software.

Version history:

• (1 0) – Initial version.

Next: , Previous: crypto ec, Up: crypto

#### 2.3.9 Elliptic Curve Digital Signature Algorithm (ECDSA)

The (weinholt crypto ec dsa) library builds on the (weinholt crypto ec) library and provides an interface similar to (weinholt crypto dsa). The keys and the operations are defined to work with elliptic curves instead of modular exponentiation.

— Procedure: make-ecdsa-public-key elliptic-curve Q

Constructs an ECDSA public key object. Q is a point on elliptic-curve. Q is only checked to be on the curve if it is in bytevector format.

— Procedure: ecdsa-public-key? obj

Returns #t if obj is an ECDSA public key object.

— Procedure: ecdsa-public-key-curve ecdsa-public-key

Returns the curve that ecdsa-public-key uses.

— Procedure: ecdsa-public-key-Q ecdsa-public-key

The point on the curve that defines ecdsa-public-key.

— Procedure: ecdsa-public-key-length ecdsa-public-key

The bitwise length of the ECDSA public key ecdsa-public-key.

— Procedure: make-ecdsa-private-key elliptic-curve [d Q]

Constructs an ECDSA private key object. d is a secret multiplier, which gives a public point Q on elliptic-curve.

If Q is omitted it is recomputed based on d and the curve. If d is omitted a random multiplier is chosen. Please note the warning about entropy at the start of this section. See crypto.

— Procedure: ecdsa-private-key? obj

Returns #t if obj is an ECDSA private key object.

— Procedure: ecdsa-private-key-d ecdsa-private-key

The secret multiplier of ecdsa-private-key.

— Procedure: ecdsa-private-key-Q ecdsa-private-key

The public point of ecdsa-private-key.

— Procedure: ecdsa-private->public ecdsa-private-key

Strips ecdsa-private-key of the secret multiplier and returns an ECDSA public key object.

— Procedure: ecdsa-private-key-from-bytevector bytevector

Parses bytevector as an ECDSA private key encoded in RFC 5915 format. A curve identifier is encoded along with the key. Currently only the curves secp256r1, secp384r1 and secp521r1 are supported.

— Procedure: ecdsa-verify-signature hash ecdsa-public-key r s

Returns #t if the signature (r,s) was made by the private key corresponding to ecdsa-public-key. The bytevector hash is the message digest that was signed.

— Procedure: ecdsa-create-signature hash ecdsa-private-key

Creates a signature of the bytevector hash using ecdsa-private-key. Returns the values r and s.

ECDSA keys are normally defined to work together with some particular message digest algorithm. RFC 5656 defines ECDSA with SHA-2 and this library provides the record types ecdsa-sha-2-public-key and ecdsa-sha-2-private-key so that keys defined to work with SHA-2 can be distinguished from other keys. Keys of this type are still usable for operations that expect the normal ECDSA key types.

— Procedure: make-ecdsa-sha-2-public-key elliptic-curve Q

Performs the same function as make-ecdsa-public-key, but the returned key is marked to be used with SHA-2.

— Procedure: ecdsa-sha-2-public-key? obj

Returns #t if obj is an ECDSA public key marked to be used with SHA-2.

— Procedure: make-ecdsa-sha-2-private-key

Performs the same function as make-ecdsa-private-key, but the returned key is marked to be used with SHA-2.

— Procedure: ecdsa-sha-2-private-key?

Returns #t if obj is an ECDSA private key marked to be used with SHA-2.

— Procedure: ecdsa-sha-2-verify-signature message ecdsa-sha2-public-key r s

The bytevector message is hashed with the appropriate message digest algorithm (see RFC 5656) and the signature (r,s) is then verified. Returns #t if the signature was made with the private key corresponding to ecdsa-sha2-public-key.

— Procedure: ecdsa-sha-2-create-signature message ecdsa-sha2-private-key

The bytevector message is hashed with the appropriate message digest algorithm (see RFC 5656) and a signature is created using ecdsa-sha2-private-key. Returns the values r and s.

— Procedure: ecdsa-sha-2-private-key-from-bytevector bytevector

Performs the same function as ecdsa-private-key-from-bytevector, except the returned value is marked to be used with SHA-2.

Version history:

• (1 0) – Initial version.

Next: , Previous: crypto ec dsa, Up: crypto

#### 2.3.10 Entropy and randomness

The (weinholt crypto entropy) library is meant to help with generating random data. It tries to use the system's /dev/urandom device if possible, otherwise it uses SRFI-27.

Please see the note at the beginning of the chapter.

— Procedure: bytevector-randomize! target [target-start k]

Writes k random bytes to the bytevector target starting at index target-start.

— Procedure: make-random-bytevector k

Returns a bytevector of length k with random content.

          (import (weinholt crypto entropy))
(make-random-bytevector 8)
⇒ #vu8(68 229 38 253 58 70 198 161)


Version history:

• (1 0) – Initial version.

Next: , Previous: crypto entropy, Up: crypto

#### 2.3.11 Message-Digest algorithm 5

The (weinholt crypto md5) library is an implementation of the cryptographic hash function MD5. It takes bytes as input and returns a message digest, which is like a one-way summary of the data. The idea is that even the smallest change in the data should produce a completely different digest, and it should be difficult to find different data that has the same digest. An MD5 digest is 16 bytes.

MD5 has a maximum message size of 2^64-1 bits.

The MD5 algorithm is considered broken and you will likely want to use SHA-2 instead, if possible.

— Procedure: md5 bv ...

The complete all-in-one procedure to calculate the MD5 message digest of all the given bytevectors in order. Returns an md5 state, which should be used with md5->bytevector or md5->string.

          (md5->string (md5 (string->utf8 "A Scheme in my pocket")))
⇒ "65A2B2D8EE076250EA0A105A8D5EF1BB"

— Procedure: md5-length

The length of md5 message digests in bytes.

— Procedure: make-md5

Returns a new MD5 state for use with the procedures below. The type of the return value is unspecified.

— Procedure: md5-update! md5state bv [start end]

Updates the md5state to include the specified range of data from bv.

— Procedure: md5-finish! md5state

Finalizes the md5state. This must be used after the last call to md5-update!.

— Procedure: md5-clear! md5state

Clear the md5state so that it does not contain any part of the input data or the message digest.

— Procedure: md5-copy md5state

Make a copy of the md5state.

— Procedure: md5-finish md5state

Performs md5-finish! on a copy of md5state and then returns the new state.

— Procedure: md5-copy-hash! md5state bv offset

Copies the message digest (a.k.a. hash) in the finalized md5state into bv at the given offset.

— Procedure: md5-96-copy-hash! md5state bv offset

Like md5-copy-hash!, but only copies the leftmost 96 bits.

— Procedure: md5->bytevector md5state

Returns a new bytevector which contains a binary representation of the finalized md5state.

— Procedure: md5->string md5state

Returns a new string which contains a textual representation of the finalized md5state. The conventional hexadecimal representation is used.

— Procedure: md5-hash=? md5state bv

Compares the finalized md5state with the leading bytes of bv. The comparison is designed to take the same amount of time regardless of where any differences may be. This may be important for networked programs that would otherwise be vulnerable to timing attacks.

— Procedure: md5-96-hash=? md5state bv

Like md5-hash=? except it only compares the leftmost 96 bits.

— Procedure: hmac-md5 secret bytevector ...

An HMAC is a Hash-based Message Authentication Code. This procedure uses MD5 to generate such a code. The return value is an MD5 state.

Version history:

• (1 0) – Initial version.
• (1 1) – Added md5-length, md5-96-copy-hash!, md5-hash=? and md5-96-hash=?.

Next: , Previous: crypto md5, Up: crypto

#### 2.3.12 OpenPGP signature verification

The (weinholt crypto openpgp) library provides procedures for reading OpenPGP keyrings and verifying signatures. OpenPGP signatures can be created with e.g. GNU Private Guard (GnuPG) and are often used to verify the integrity of software releases.

Version 4 keys and version 3/4 signatures are supported. The implemented public key algorithms are RSA and DSA, and it verifies signatures made using the message digest algorithms MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 (all the standard algorithms except RIPE-MD160).

An OpenPGP key is actually a list of OpenPGP packets with a certain structure: first is the primary key (e.g. an RSA or DSA key), next possibly a revocation, then a number of user IDs, attributes, signatures and also subkeys (which are just like primary keys, except marked as subkeys). See RFC 4880 section 11 for the exact composition. This library represents keyrings as hashtables indexed by key ID and where the entries are lists of packets in the order they appeared in the keyring file.

Please note that this library assumes the program that wrote the keyring did due diligence when importing keys, and made sure that e.g. subkey binding signatures are verified, and that the order of packets is correct.

— Procedure: port-ascii-armored? port

Returns false if the data at the beginning of port doesn't look like a valid binary OpenPGP packet. The port must be a binary input port. The port position is not changed.

— Procedure: get-openpgp-packet port

Reads an OpenPGP packet from port, which must be a binary input port. An error is raised if the packet type is unimplemented.

— Procedure: get-openpgp-keyring p

Reads a keyring from the binary input port p. Returns a hashtable where all primary keys and subkeys are indexed by their key ID (an integer). The values in the hashtable are lists that contain all OpenPGP packets associated with each key. No effort at all is made to verify that keys have valid signatures.

Warning: this can take a while if the keyring is very big.

— Procedure: get-openpgp-keyring/keyid p keyid

Searches the binary input port p for the public key with the given keyid. Returns a hashtable similar to get-openpgp-keyring, except it will only contain the primary and subkeys associated with the keyid.

The keyid can be either a 64 or 32 bit exact integer.

Warning: this is faster than get-openpgp-keyring, but is still rather slow with big keyrings. The speed depends on the SHA-1 implementation.

— Procedure: get-openpgp-detached-signature/ascii p

Reads a detached OpenPGP signature from the textual input port p. Returns either an OpenPGP signature object or the end of file object.

These signatures can be created with e.g. gpg -a --detach-sign filename.

— Procedure: verify-openpgp-signature sig keyring p

Verifies the signature data in sig. The keyring hashtable is used to find the public key of the signature issuer. The signed data is read from the binary input port p.

This procedure returns two values. These are the possible combinations:

• good-signature key-data – The signature matches the data. The key-data contains the public key list that was used to verify the signature.
• bad-signature key-data – The signature does not match the data. The key-data is the same as above.
• missing-key key-id – The issuer public key for the signature was not found in the keyring. The key-id is the 64-bit key ID of the issuer.

— Procedure: openpgp-signature? obj

True if obj is an OpenPGP signature object. Such objects are read with get-openpgp-detached-signature/ascii and are also contained in keyring entries.

— Procedure: openpgp-signature-issuer sig

The 64-bit key ID of the OpenPGP public key that issued the signature sig.

— Procedure: openpgp-signature-public-key-algorithm sig

Returns the name of the public key algorithm used to create the signature sig. This is currently the symbol dsa or rsa.

— Procedure: openpgp-signature-hash-algorithm sig

The name of the message digest algorithm used to create the signature sig. This is currently one of md5, sha-1, ripe-md160 (unsupported), sha-224, sha-256, sha-384 or sha-512.

— Procedure: openpgp-signature-creation-time sig

An SRFI-19 date object representing the time at which the signature sig was created.

— Procedure: openpgp-signature-expiration-time sig

An SRFI-19 date object representing the time at which the signature sig expires. Returns #f if there's no expiration time.

— Procedure: openpgp-user-id? obj

True if obj is an OpenPGP user id.

— Procedure: openpgp-user-id-value user-id

The string value of the user-id. This is often the name of the person who owns the key.

— Procedure: openpgp-user-attribute? obj

True if obj is an OpenPGP user attribute. Attributes are used to encode JPEG images. There's currently no way to access the image.

— Procedure: openpgp-public-key? obj

True if obj is an OpenPGP primary key or subkey.

— Procedure: openpgp-public-key-subkey? key

True if obj is a subkey.

— Procedure: openpgp-public-key-value key

The DSA or RSA public key contained in the OpenPGP public key. The value returned has the same type as the (crypto weinholt dsa) or (crypto weinholt rsa).

— Procedure: openpgp-public-key-fingerprint key

The fingerprint of the OpenPGP public key as a bytevector. This is an SHA-1 digest based on the public key values.

— Procedure: openpgp-format-fingerprint bv

Formats the bytevector bv, which was presumably created by openpgp-public-key-fingerprint, as a string in the format preferred for PGP public key fingerprints.

— Procedure: openpgp-public-key-id key

The 64-bit key ID of the OpenPGP public key.

Version history:

• (1 0) – Initial version.
• (1 1) – Added get-openpgp-packet and port-ascii-armored?.

Next: , Previous: crypto openpgp, Up: crypto

The procedure provided by (weinholt crypto password) is the same type of procedure that is called crypt in the standard C library. It is used for password hashing, i.e. it scrambles passwords. This is a method often used when passwords need to be stored in databases.

The scrambling algorithms are based on cryptographic primitives but have been modified so that they take more time to compute. They also happen to be quite annoying to implement.

Only DES and MD5 based hashes are currently supported.

Scrambles a password using the given salt. The salt can also be a hash. The returned hash will be prefixed by the salt.

A fresh random salt should be used when hashing a new password. The purpose of the salt is to make it infeasible to reverse the hash using lookup tables.

To verify that a password matches a hash, you can do something like (string=? hash (crypt password hash)).

          (import (weinholt crypto password))
(crypt "test" "..")
⇒ "..9sjyf8zL76k"

          (crypt "test" "$1$RQ3YWMJd$") ⇒ "$1$RQ3YWMJd$oIomUD5DCxenAs2icezcn."

          (string=? "$1$ggKHY.Dz$fNBcmNFTa1BFGXoLsRDkS." (crypt "test" "$1$ggKHY.Dz$fNBcmNFTa1BFGXoLsRDkS."))
⇒ #t


Version history:

• (1 0) – Initial version.

Next: , Previous: crypto password, Up: crypto

#### 2.3.14 RSA public key encryption and signatures

The (weinholt crypto rsa) library implements the RSA (Rivest, Shamir and Adleman) algorithm and a few helpers.

— Procedure: make-rsa-public-key n e

Returns an RSA public key object containing the modulus n and the public exponent e.

— Procedure: rsa-public-key? obj

True if obj is a public RSA key.

— Procedure: rsa-public-key-n key
— Procedure: rsa-public-key-modulus key

Returns the modulus of key.

— Procedure: rsa-public-key-e key
— Procedure: rsa-public-key-public-exponent key

Returns the public exponent of key.

— Procedure: rsa-public-key-from-bytevector bytevector

Parses bytevector as an ASN.1 DER encoded public RSA key. The return value can be used with the other procedures in this library.

— Procedure: rsa-public-key-length key

Returns the number of bits in the modulus of key. This is also the maximum length of data that can be encrypted or decrypted with the key.

— Procedure: rsa-public-key-byte-length key

Returns the number of 8-bit bytes required to store the modulus of key.

— Procedure: make-rsa-private-key n e d [p q exponent1 exponent2 coefficient]

Returns an RSA private key object with the given modulus n, public exponent e, and private exponent d.

The other parameters are used to improve the efficiency of rsa-encrypt. They are optional and will be computed if they are omitted.

— Procedure: rsa-private-key? obj

True if obj is a private RSA key.

— Procedure: rsa-private-key-n key
— Procedure: rsa-private-key-modulus key

Returns the modulus of key.

— Procedure: rsa-private-key-public-exponent key

Returns the public exponent of key. This exponent is used for encryption and signature verification.

— Procedure: rsa-private-key-d key
— Procedure: rsa-private-key-private-exponent key

Returns the private exponent of key. This exponent is used for decryption and signature creation.

— Procedure: rsa-private-key-prime1 key
— Procedure: rsa-private-key-prime2 key

These two procedures return the first and second prime factors (p,q) of the modulus (n=pq).

— Procedure: rsa-private-key-exponent1 key

This should be equivalent to (mod d (- p 1)). It is used to speed up rsa-decrypt.

— Procedure: rsa-private-key-exponent2 key

This should be equivalent to (mod d (- q 1)). It is used to speed up rsa-decrypt.

— Procedure: rsa-private-key-coefficient key

This should be equivalent to (expt-mod q -1 p). It is used to speed up rsa-decrypt.

— Procedure: rsa-private->public key

Uses the modulus and public exponent of key to construct a public RSA key object.

— Procedure: rsa-private-key-from-bytevector bytevector

Parses bytevector as an ASN.1 DER encoded private RSA key. The return value can be used with the other procedures in this library.

— Procedure: rsa-private-key-from-pem-file filename

Opens the file and reads a private RSA key. The file should be in Privacy Enhanced Mail (PEM) format and contain an ASN.1 DER encoded private RSA key.

Encrypted keys are currently not supported.

— Procedure: rsa-encrypt plaintext key

Encrypts the plaintext integer using the key, which is either a public or private RSA key.

plaintext must be an exact integer that is less than the modulus of key.

— Procedure: rsa-decrypt ciphertext key

Decrypts the ciphertext integer using the key, which must be a private RSA key.

ciphertext must be an exact integer that is less than the modulus of key.

          (import (weinholt crypto rsa))
(let ((key (make-rsa-private-key 3233 17 2753)))
(rsa-decrypt (rsa-encrypt 42 key) key))
⇒ 42

— Procedure: rsa-decrypt/blinding ciphertext key

This performs the same function as rsa-decrypt, but it uses RSA blinding. It has been shown that the private key can be recovered by measuring the time it takes to run the RSA decryption function. Use RSA blinding to protect against these timing attacks.

For more technical information on the subject, see Paul C. Kocher's article Timing Attacks on Implementations of Diffie-Hellman, RSA, DSS, and Other Systems.

It is often not enough to just use the plain encryption and decryption procedures; a protocol for what to put in the plaintext should also be used. PKCS #1 (RFC 3447) is a standard for how to perform RSA encryption and signing with padding. New protocols should use one of the other protocols from the RFC.

— Procedure: rsa-pkcs1-encrypt plaintext public-key

Pads and encrypts the plaintext bytevector using public-key, a public RSA key. The return value is an integer.

The plaintext can't be longer than the length of the key modulus, in bytes, minus 11.

— Procedure: rsa-pkcs1-decrypt ciphertext private-key

The inverse of rsa-pkcs1-encrypt. Decrypts the ciphertext integer using private-key, a private RSA key. The padding is then checked for correctness and removed.

          (import (weinholt crypto rsa))
(let ((key (make-rsa-private-key
288412728347463293650191476303670753583
65537
190905048380501971055612558936725496993)))
(utf8->string
(rsa-pkcs1-decrypt
(rsa-pkcs1-encrypt (string->utf8 "Hello")
(rsa-private->public key))
key)))
⇒ "Hello"

— Procedure: rsa-pkcs1-decrypt-signature signature public-key

Decrypts the signature (a bytevector) contained in the signature integer by using the public-key. The signature initially contains PKCS #1 padding, but this is removed.

— Procedure: rsa-pkcs1-decrypt-digest signature public-key

This performs the same operation as rsa-pkcs1-decrypt-signature, except it then treats the decrypted signature as a DER encoded DigestInfo. The return value is a list containing a digest algorithm specifier and a digest.

Version history:

• (1 0) – Initial version.
• (1 1) – Implemented private key operations.

Next: , Previous: crypto rsa, Up: crypto

#### 2.3.15 Secure Hash Algorithm 1

The interface provided by (weinholt crypto sha-1) is identical to the one provided by the MD5 library, except every procedure is prefixed by sha-1 instead of md5. See crypto md5.

SHA-1 also has a maximum message size of 2^64-1 bits, but the message digests are 160 bits instead of MD5's 128. Version history:

• (1 0) – Initial version.
• (1 1) – Added sha-1-length, sha-1-96-copy-hash!, sha-1-hash=? and sha-1-96-hash=?.

Next: , Previous: crypto sha-1, Up: crypto

#### 2.3.16 Secure Hash Algorithm 2

The interface provided by (weinholt crypto sha-2) is identical to the one provided by the MD5 library, but instead of md5, every procedure is prefixed by sha-224, sha-256, sha-384 or sha-512. In addition the procedures that operate on the leftmost 96 bits are instead defined for the leftmost 128 bits (e.g. sha-512-128-hash=?). See crypto md5.

SHA-224 and SHA-256 have a maximum message size of 2^64-1 bits. For SHA-384 and SHA-512 the maximum is 2^128-1 bits. The message digests produced by SHA-224 are 224 bits, and so on. Version history:

• (0 0) – Initial version.
• (1 1) – Added sha-224-length, sha-256-length, sha-384-length, sha-512-length that return the length of a digest in bytes. Added the comparison predicates sha-224-hash=?, sha-256-hash=?, sha-384-hash=? sha-512-hash=? that run in constant time. Added procedures for truncated digests: sha-224-128-hash=?, sha-256-128-hash=?, sha-384-128-hash=? sha-512-128-hash=?, sha-224-128-copy-hash!, sha-256-128-copy-hash!, sha-384-128-copy-hash! and sha-512-128-copy-hash!. Now uses the correct definition of HMAC-SHA-384 and HMAC-SHA-512. The HMACs now also handle key lengths larger than the block size.

Next: , Previous: crypto sha-2, Up: crypto

#### 2.3.17 SSH public key format conversion

Use (weinholt crypto ssh-public-key) to convert public RSA, DSA, and ECDSA keys from records to the binary SSH public key format, and the other way around. SSH is the name of a network protocol for secure terminal connections defined by RFCs 4250-4254. The key format is specified by RFC 4716. ECDSA keys are specified by RFC 5656.

The types used for RSA, DSA and ECDSA keys in this library are the same types used elsewhere. The ECDSA keys must have the record type ecdsa-sha-2-public-key.

Future work would be to implement parsing of the various textual formats that contain Base64 public SSH keys.

— Procedure: get-ssh-public-key p

Reads a public RSA/DSA/ECDSA key encoded in the SSH public key format from the binary input port p.

— Procedure: ssh-public-key->bytevector key

Converts the public RSA/DSA/ECDSA key to the SSH public key format.

— Procedure: ssh-public-key-algorithm key

Returns the SSH algorithm identifier of key. For RSA keys this is "ssh-rsa", for DSA keys it is "ssh-dss", and for ECDSA keys it is "ecdsa-sha2-[identifier]" where [identifier] identifies the curve.

— Procedure: ssh-public-key-fingerprint key

The MD5 based fingerprint of the RSA/DSA/ECDSA key in the same format used by common SSH software and specified by RFC 4716.

— Procedure: ssh-public-key-random-art key

The random art of the RSA/DSA/ECDSA key. This is a visual representation of the key can is easier for humans to distinguish than fingerprints. This is the same art that OpenSSH's VisualHostKey feature displays.

Version history:

• (1 0) – Initial version.
• (1 1) – Added ssh-public-key-algorithm. Added support for ecdsa-sha2-* keys using the elliptic curves nistp256, nistp384, and nistp521.

Previous: crypto ssh-public-key, Up: crypto

#### 2.3.18 X.509 Public-Key Infrastructure

The (weinholt crypto x509) library implements parts of ITU-T's X.509 standard for public-key infrastructure.

An X.509 certificate is a data structure that contains a public RSA or DSA key and some identifying information. There is a subject and an issuer (and lots of details). The subject specifies who the certificate belongs to, and the issuer specifies who signed it. Certificate path validation is used to get from a trusted issuer to the subject, often via several intermediates. X.509 certificates are used in many places, e.g. TLS, S/MIME email and IPsec.

— Procedure: certificate? obj

True if obj is an X.509 certificate.

— Procedure: certificate-from-bytevector bv [start end]

Reads an X.509 certificate from the bytevector bv. The certificate is in the ASN.1 DER format customarily used for X.509 certificates. For certificates in PEM format, first read them with get-delimited-base64. See text base64.

— Procedure: certificate-public-key certificate

Returns the public key contained in the certificate. The return value's type is either an RSA or a DSA public key. See crypto dsa. See crypto rsa.

— Procedure: validate-certificate-path path [common-name time CA-cert]

Returns ok if the certificates in the path list form a valid certificate path. A valid certificate path begins with a trusted CA certificate and ends with an end entity's certificate. Each certificate in the chain signs the next certificate. This is intended to form a chain of trust from a certificate you already trust (the CA certificate) to a new certificate, the end entity's certificate.

Optionally a common-name string can be given. This is normally a good idea. If you've tried to connect to a service at the domain name example.com, you might like to know that the certificate it presents actually belongs to example.com. Both the common name and subjectAltName fields of the certificate are checked. Currently only tested with domain names.

An SRFI-19 time can also optionally be given, in which case it is used instead of the system's current time.

If the optional CA-cert argument is given it is a trusted certificate that will be used to validate the start of the path. If this argument is given then no other trusted certificates will be tried.

— Parameter: CA-path
— Parameter: CA-file
— Parameter: CA-procedure

These SRFI-39 parameters can be used to provide the validate-certificate-path procedure with trusted Certificate Authority (CA) certificates, also known as root certificates. It is beyond the scope of this library collection to provide you with trusted certificates. Many operating systems have such collections, e.g. Debian's ca-certificates package. Technically, a CA certificate is a self-issued certificate with correctly set “basic constraints” and “key usage” attributes. The CA-path parameter should be the name (ending in the path separator character, if any) of a directory containing files named by OpenSSL's c_rehash program. The files contain PEM encoded CA certificates. The filenames are partially a hash which also can be retrieved from the name-hash value in the issuer/subject alists. Default: "/etc/ssl/certs/".

The CA-file parameter is not yet implemented. In the future this will be the name of a file which contains trusted certificates. Default: "/etc/ssl/certs/ca-certificates.crt".

The CA-procedure parameter is a procedure which takes a single argument: an issuer alist. If you have the requested certificate, return it. Otherwise return #f. For forward compatibility the procedure should accept any number of arguments. Default: (lambda (issuer . _) #f)

The following part of the library is for more advanced uses.

— Procedure: certificate-key-usage certificate

Returns the keyUsage extension data from certificate. If the extension is absent then the return value is #f. Otherwise it is a list in which the possible entries are: digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly, and decipherOnly. See RFC 5280 for an explanation of their meaning. If you are implementing a protocol where keyUsage is important, the specification will probably mention it.

— Procedure: certificate-tbs-data certificate

Returns the To Be Signed (TBS) part of certificate as a DER encoded bytevector. Except for the certificate's signature, the whole certificate is contained in the TBS data.

— Procedure: decipher-certificate-signature subject-cert issuer-cert

Uses the public key of issuer-cert to decipher the signature on subject-cert.

Version history:

• (0 0) – Initial version.

Next: , Previous: crypto, Up: Library reference

### 2.4 Machine code disassemblers

All disassemblers provided here use the same method of signalling undefined/invalid opcodes. The following procedure can be used to guard against such errors:

— Procedure: invalid-opcode? obj

When an invalid opcode is encountered an exception with the &invalid-opcode condition is raised. Use invalid-opcode? to guard against it.

The disassemblers take an argument that is called a collector. It is either #f or a procedure of the following form: (lambda (tag . bytes) body). The tag is specific to the architecture, but the bytes are the bytes forming the instruction. The procedure is used to tell the caller what function each byte of an instruction performs. This works best for architectures that use variable-length instructions. For most instructions there will be multiple calls to the collector.

Next: , Up: disassembler

#### 2.4.1 Intel 8080/8085 disassembler

The (weinholt disassembler i8080) library provides a disassembler for the Intel 8080 architecture. It was an 8-bit architecture used in many micros and even the DEC VT100. It was also the predecessor of the Intel 8086.

— Procedure: get-instruction binary-input-port collector

Reads one instruction from the binary-input-port and returns it in symbolic form. For a description of the collector, see disassembler.

          (import (weinholt disassembler i8080))
(get-instruction (open-bytevector-input-port
#vu8(#x22 #x01 #x01))
#f)
⇒ (shld (mem16+ 257))


Version history:

• (1 0) – Initial version.

Next: , Previous: disassembler i8080, Up: disassembler

#### 2.4.2 Freescale 68HC12 disassembler

The (weinholt disassembler m68hc12) library provides a disassembler for the Freescale 68HC12 architecture (formerly Motorola 68HC12 and sometimes called 68HCS12, HC12 or CPU12). It is a 16-bit architecture used in microcontrollers.

— Procedure: get-instruction binary-input-port collector

Reads one instruction from the binary-input-port and returns it in symbolic form. For a description of the collector, see disassembler.

          (import (weinholt disassembler m68hc12))
(get-instruction (open-bytevector-input-port
#vu8(#x18 #x01 #xAE #x00 #x00))
#f)
⇒ (movw (0) (pre- 2 sp))


Version history:

• (1 0) – Initial version.

Next: , Previous: disassembler m68hc12, Up: disassembler

#### 2.4.3 MIPS II disassembler

The (weinholt disassembler mips) library provides a disassembler for most 32-bit MIPS II instructions. MIPS is a RISC architecture and all instructions have the same length.

— Procedure: get-instruction binary-input-port endianness collector

Disassembles one instruction from the binary-input-port and returns it in symbolic form. The endianness specifies if instructions are read in big or little endianness. For a description of the collector, see disassembler.

          (import (weinholt disassembler mips))
(get-instruction (open-bytevector-input-port
#vu8(#x10 #x40 #x00 #x02))
(endianness big)
#f)
⇒ (beq $v0$zero (\$pc 8))


Version history:

• (1 0) – Initial version.

Previous: disassembler mips, Up: disassembler

#### 2.4.4 Intel x86-16/32/64 disassembler

The (weinholt disassembler x86) library is a disassembler for the Intel x86 architecture. It supports 16-bit, 32-bit and 64-bit modes as well as most modern instruction encodings, including the VEX prefix used by Intel AVX.

The disassembler does not keep track of the instruction pointer, so relative offsets are returned as they appear in the instruction encoding. If you wish to show the destination for branches, or the actual offset for AMD64's RIP-relative addressing, you will need to compute the offset yourself.

— Procedure: get-instruction binary-input-port mode collector

Reads a single instruction from the given binary-input-port. The mode is one of 16, 32 or 64 (which roughly correspond to real, protected and long mode).

The collector is either #f or a procedure that takes a symbolic tag and a variable number of bytes. The tag is one of the symbols modr/m, sib, disp, immediate, /is4, prefix and opcode. The x86 instruction set uses variable length instructions (of up to 15 bytes) and the collector procedure can be used to find out the type of data each byte of an instruction contains.

The returned instructions have the same operand order as Intel's documentation uses, i.e. the left operand is the destination.

          (import (weinholt disassembler x86))
(get-instruction (open-bytevector-input-port
#vu8(#x69 #x6c #x6c #x65 #x01 #x00 #x00 #x00))
64 #f)
⇒ (imul ebp (mem32+ rsp 101 (* rbp 2)) 1)

          (get-instruction (open-bytevector-input-port
#vu8(196 227 113 72 194 49))
64 (lambda x (display x) (newline)))
-| (prefix 196 227 113)
-| (opcode 72)
-| (modr/m 194)
-| (/is4 49)
⇒ (vpermiltd2ps xmm0 xmm1 xmm2 xmm3)

          (get-instruction (open-bytevector-input-port #vu8(#xEB #x20))
64 #f)
⇒ (jmp (+ rip 32))


Version history:

• (1 0) – Initial version.
• (1 1)get-instruction reads at most 15 bytes.

Next: , Previous: disassembler, Up: Library reference

### 2.5 Network protocols

Next: , Up: net

#### 2.5.1 Internet Relay Chat

The (weinholt net irc) library provides low-level procedures for parsing and formatting IRC protocol commands. It makes it easy to split incoming commands into parts and to format outgoing commands. There are also helpers for various other parsing needs.

The IRC protocol is standardized by RFCs 2810-2813, but servers very often (always?) disregard the RFCs. They do provide good guidelines for what should work.

— Procedure: parse-message message [remote-server]

This procedure splits an IRC message into three parts: prefix, command and a list of arguments. The command is either a symbol or a number. If the message does not have a prefix the remote-server argument will be used instead, because it is implied by the protocol.

          (import (weinholt net irc))
(parse-message
":irc.example.net PONG irc.example.net :irc.example.net")
⇒ "irc.example.net"
⇒ PONG
⇒ ("irc.example.net" "irc.example.net")

          (parse-message
":user!ident@example.com PRIVMSG #test :this is a test")
⇒ "user!ident@example.com"
⇒ PRIVMSG
⇒ ("#test" "this is a test")

          (parse-message "PING irc.example.net" "irc.example.net")
⇒ "irc.example.net"
⇒ PING
⇒ ("irc.example.net")

          (parse-message "PING irc.example.net")
⇒ #f
⇒ PING
⇒ ("irc.example.net")

— Procedure: parse-message-bytevector bv [start end remote-server]

This procedure does the same thing parse-message does, except it works on bytevectors. This is useful because the IRC protocol does not have a standard character encoding. Different channels on IRC often use different encodings.

— Procedure: format-message-raw port codec prefix cmd parameters ...

Formats and outputs an IRC message to the given port, which must be in binary mode.

The codec is a codec, meaning the value returned by e.g. utf-8-codec or latin-1-codec. The codec is used to transcode the parameters.

The prefix is the name of the server or client that originated the message. IRC clients should use #f as prefix when sending to a server.

The cmd is a symbol or string representing an IRC command, but it can also be an integer (which must be be between 000 and 999). Only servers send numerical commands.

The rest of the arguments are the parameters for the given command, which can be either numbers, strings or bytevectors. Only the last of the parameters may contain whitespace. The maximum number of parameters allowed by the protocol is 15. Each IRC protocol command takes a pre-defined number of parameters, so e.g. if cmd is PRIVMSG then you must only pass two parameters.

          (import (weinholt net irc))
(utf8->string
(call-with-bytevector-output-port
(lambda (port)
(format-message-raw port (utf-8-codec)
"irc.example.net" 1 "luser"
"Welcome to the IRC"))))
⇒ ":irc.example.net 001 luser :Welcome to the IRC\r\n"

          (utf8->string
(call-with-bytevector-output-port
(lambda (port)
(format-message-raw port (utf-8-codec)
#f 'NOTICE "#example"
"Greetings!"))))
⇒ "NOTICE #example Greetings!\r\n"

— Procedure: format-message-and-verify port codec prefix cmd parameters ...

This procedure works just like format-message-raw, except before writing the message it parses the formatted message and compares it with the input to make sure it is the same. This prevents some attacks against IRC bots.

          (import (weinholt net irc))
(utf8->string
(call-with-bytevector-output-port
(lambda (port)
(format-message-and-verify
port (utf-8-codec) #f 'NOTICE
"#scheme" "announcing the 2^32th irc library!"))))
⇒ "NOTICE #scheme :announcing the 2^32th irc library!\r\n"


This example shows what happens when a parameter contains a newline, which is a common attack against bots. The command after the newline would be sent to the server, and the bot would exit all channels. Instead an exception is raised:

          (utf8->string
(call-with-bytevector-output-port
(lambda (port)
(format-message-and-verify
port (utf-8-codec) #f 'NOTICE
"#example" "Querent: the answer is \r\nJOIN 0"))))
error--> &irc-format

— Procedure: format-message-with-whitewash port codec prefix cmd parameters ...

This provides an alternative to format-message-and-verify which is useful if you're not concerned about data integrity, so to speak. It replaces all bad characters with space before transmitting.

          (utf8->string
(call-with-bytevector-output-port
(lambda (port)
(format-message-with-whitewash
port (utf-8-codec) #f 'NOTICE
"#example" "Querent: the answer is \r\nJOIN 0"))))
⇒ "NOTICE #example :Querent: the answer is   JOIN 0\r\n"

— Procedure: irc-parse-condition? obj

Returns #t is obj is an &irc-parse condition. The message parsing procedures use this condition when they detect a malformed message.

— Procedure: irc-format-condition? obj

Returns #t is obj is an &irc-format condition. The message formatting procedures use this condition when they are unable to format a message.

— Procedure: extended-prefix? str

The prefix in an IRC message can either be a server name or an extended prefix which identifies a client. Extended prefixes look like nickname!user@host.

— Procedure: prefix-split str

Splits an extended prefix into its parts and returns three values: nickname, user and host.

— Procedure: prefix-nick str

Returns the nickname part of an extended prefix.

— Procedure: parse-isupport list

Parses an ISUPPORT list. The return value is an alist.

See http://www.irc.org/tech_docs/005.html for more on ISUPPORT.

— Procedure: isupport-defaults

Returns an alist of default ISUPPORT values.

— Procedure: string-irc=? str1 str2 [mapping]

Compares str1 and str2 for equality. The comparison is case-insensitive and uses the specified mapping to compare characters. This procedure is useful for comparing nicknames.

The mapping should be one of rfc1459, ascii or strict-rfc1459. Servers indicate in the CASEMAPPING ISUPPORT parameter which mapping they use.

The first IRC servers used Swedish ASCII for nicknames, so the nicknames sm|rg}s and SM\RG]S are equivalent on some servers.

— Procedure: string-upcase-irc str mapping

Upcases str using the given case mapping.

— Procedure: string-downcase-irc str mapping

Downcases str using the given case mapping.

— Procedure: ctcp-message? str

Returns #t if the str represents a CTCP message. This is currently the extent of this library's CTCP support. CTCP is used for sending files, opening direct connections between clients, checking client versions, asking for the time, pinging clients, doing “action” style messages, and some other stuff.

— Procedure: irc-match? pattern input

Returns #t if the pattern, which can contain wildcards, matches the input. Otherwise returns #f. Strings containing wildcards are called masks, and they are used in e.g. channel ban lists.

The pattern follows the syntax specified in section 2.5 of RFC2812. A #\* matches zero or more characters and #\? matches any single character. The comparison is case-insensitive. Wildcard characters can be escaped with #\\.

          (import (weinholt net irc))
(irc-match? "a?c" "abc")
⇒ #t
(irc-match? "a*c" "ac")
⇒ #t
(irc-match? "a*c" "acb")
⇒ #f

— Procedure: parse-channel-mode prefix chanmodes mode-list

Uses the ISUPPORT data in prefix and chanmodes to parse a MODE command for a channel. The target is not included in the mode-list. To keep track of changes to who is op'd and voice'd (and half-op'd) you can use this procedure together with the server's ISUPPORT PREFIX data.

          (parse-channel-mode (cdr (assq 'PREFIX (isupport-defaults)))
(cdr (assq 'CHANMODES (isupport-defaults)))
'("+o-o+e-e+l-l+km+-be"
"op" "deop" "ex" "unex"
"50" "key" "unban"))
⇒
((+ #\o "op")
(- #\o "deop")
(+ #\e "ex")
(- #\e "unex")
(+ #\l "50")
(- #\l #f)
(+ #\k "key")
(+ #\m channel)
(- #\b "unban")
(? #\e channel))


Version history:

• (1 0) – Initial version.
• (2 0) – Replaced swe-ascii-string-ci=? with string-irc=?, which uses the CASEMAPPING ISUPPORT parameter. Added string-upcase-irc, string-downcase-irc, parse-isupport, isupport-defaults and ctcp-message?.
• (2 1) – Added irc-match?.
• (2 2) – Added parse-channel-mode and fixed handling of intra-word whitespace in the parser and empty parameters in the formatter.

Next: , Previous: net irc, Up: net

#### 2.5.2 Blowcrypt/FiSH encryption for IRC

The (weinholt net irc fish) library provides procedures for interacting with IRC clients that use Blowcrypt/FiSH encryption. Messages are encrypted with Blowfish in ECB mode and then encoded with a peculiar base64 encoding. Keys can be exchanged with Diffie-Hellman (vulnerable to middleman attacks) or they can be pre-shared. FiSH is useful if you want to draw attention to your communications.

There is currently no way to initialize key-exchange.

Blowcrypt/FiSH supports both private messages and public channels. If you only need private messages then OTR provides a much better protocol. See net otr.

— Procedure: fish-message? str

Returns #f is the string is not a FiSH message.

— Procedure: fish-decrypt-message msg key

Decrypts a FiSH message. The msg is the line that the remote client sent to you.

— Procedure: fish-encrypt-message msg key

Encrypts the string msg with FiSH encryption. Returns a string containing the plaintext. There is no verification that the key was correct and the returned string might be garbage.

— Procedure: fish-key-init? str

Returns #f is str is not a FiSH key-exchange initialization request.

— Procedure: fish-generate-key init-msg

Finishes the DH1080 key-exchange request contained in init-msg. Returns two values: the newly generated key and a response for the remote client. There is no protection against middleman attacks.

— Procedure: make-fish-key str

The str is expanded and can then be used with fish-decrypt-message and fish-encrypt-message.

Version history:

• (1 0) – Initial version.

Next: , Previous: net irc fish, Up: net

#### 2.5.3 Off-the-Record Messaging

The (weinholt net otr) library provides Off-the-Record Messaging (OTR), which is a security protocol for private chat. It can be tunneled over any protocol that guarantees in-order delivery (e.g. IRC or XMPP). It provides encryption, authentication, deniability and perfect forward secrecy.

This library does not manage user identities, which is something the OTR Development Team's C library does. This choice was made to keep the implementation simple and focused on the protocol only.

The website for OTR is http://www.cypherpunks.ca/otr/.

— Procedure: otr-message? str

Returns #t if str, which is a message from a remote party, contains an OTR message. If it is an OTR message you should look up the OTR state that corresponds to the remote party (possibly make a new state) and call otr-update!.

— Procedure: make-otr-state dsa-key mss [instance-tag [versions]]

Creates an OTR state value given the private DSA key dsa-key and a maximum segment size mss. The state is used to keep track of session keys and incoming message fragments.

The dsa-key must have a 160-bit q-parameter because of details in the protocol and limitations of other implementations. A 1024-bit DSA key will work. See crypto dsa.

The maximum segment size mss is used to split long OTR messages into smaller parts when OTR is used over a protocol with a maximum message size, e.g. IRC.

If an instance-tag is specified it must be a 32-bit integer not less than #x100. If it is omitted or #f an instance tag will be randomly generated. OTR version 3 uses the instance tags to identify which OTR state messages belongs to. Be sure to read the documentation for otr-state-our-instance-tag. New for Industria 1.5.

If versions is not omitted it must be a list of acceptable OTR protocol versions. The default is (2 3). New for Industria 1.5.

— Procedure: otr-update! state str

Processes the str message, which came from the remote party, and updates the state. Use otr-empty-queue! to retrieve scheduled events.

— Procedure: otr-send-encrypted! state msg

This is used to send a message to the remote party. It encrypts and enqueues the msg bytevector and updates the state. Use otr-empty-queue! to retrieve the encrypted and formatted messages that should be sent to the remote party.

The msg must not contain a NUL (0) byte.

— Procedure: otr-authenticate! state secret [question]

Initiate or respond to an authentication request. After calling this procedure you should use otr-empty-queue!, just like with otr-send-encrypted!.

The authentication protocol can be used to verify that both partyies know the secret bytevector. The secret is never revealed over the network and is not even transmitted in an encrypted form. The protocol used is the Socialist Millionaires' Protocol (SMP), which is based on a series of zero-knowledge proofs.

— Procedure: otr-empty-queue! state

Returns and clears the event queue. The queue is a list of pairs where the symbol in the car of the pair determines its meaning. These are the possible types:

• (outgoing . line) – The cdr is a string that should be sent to the remote party.
• (encrypted . msg) – The cdr is a string that contains a decrypted message that was sent by the remote party.
• (unencrypted . msg) – The cdr is a string that was sent unencrypted by the remote party. This happens when a whitespace-tagged message is received.
• (session-established . whence) – A session has been established with the remote party. It is now safe to call otr-state-their-dsa-key, otr-state-secure-session-id, otr-send-encrypted! and otr-authenticate!. The cdr is the symbol from-there if the session was initiated by the remote party. Otherwise it is from-here.
• (session-finished . whom) – The session is now finished and no new messages can be sent over it. The cdr is either the symbol by-them or by-us. Note: there is currently no way to finish the session from the local side, so by-us is not used yet.
• (authentication . expecting-secret) – The remote party has started the authentication protocol and now expects you to call otr-authenticate!.
• (authentication . #t) – The authentication protocol has succeeded and both parties had the same secret.
• (authentication . #f) – The authentication protocol has failed. The secrets were not identical.
• (authentication . aborted-by-them) – The remote party has aborted the authentication protocol.
• (authentication . aborted-by-us) – The local party has encountered an error and therefore aborted the authentication protocol.
• (they-revealed . k) – The remote party revealed an old signing key. This is a normal part of the protocol and the key is sent unencrypted to ensure the deniability property. You might like to reveal the key somehow yourself in case you're tunneling OTR over an encrypted protocol.
• (we-revealed . k) – The local party has revealed an old signing key. Note: currently not used.
• (undecipherable-message . #f) – An encrypted message was received, but it was not possible to decrypt it. This might mean e.g. that the remote and local parties have different sessions or that a message was sent out of order.
• (remote-error . msg) – The remote party encountered a protocol error and sent a plaintext error message (probably in English).
• (local-error . con) – There was an exception raised during processing of a message. The cdr is the condition object.
• (symmetric-key-request . (protocol . data)) – The remote party has requested that the extra symmetric key be used to communicate in some out-of-band protocol. See otr-send-symmetric-key-request!. New for Industria 1.5.

For forward-compatibility you should ignore any pair with an unknown car. Most messages are quite safe to ignore if you don't want to handle them.

— Procedure: otr-state-their-dsa-key state

Returns the remote party's public DSA key. This should be used to verify the remote party's identity. If the SMP authentication protocol succeeds you can remember the hash of the key for the next session. The user could also verify the key's hash by cell phone telephone or something.

— Procedure: otr-state-our-dsa-key state

Returns the local party's private DSA key. This is useful when the user is on the phone with the remote party. First convert it to a public key with dsa-private->public and then hash it with otr-hash-public-key.

— Procedure: otr-hash-public-key public-dsa-key

Hashes a public DSA key and formats it so that it can be shown to the OTR user.

— Procedure: otr-state-secure-session-id state

Returns the secure session ID associated with the OTR state.

— Procedure: otr-format-session-id id

Formats a secure session ID in the format that is recommended when the ID should be shown to the OTR user.

The first part of the ID should be shown in bold if the session was initiated by the local party. Otherwise the second part should be bold.

— Procedure: otr-state-version state

The OTR protocol version used by the state. This is either the integer 2 or the integer 3. New for Industria 1.5.

— Procedure: otr-state-mss state

Returns the current maximum segment size of the OTR state.

— Procedure: otr-state-mss-set! state int

Sets int as the maximum segment size of the OTR state.

OTR protocol version 3 defines an extra symmetric key.

— Procedure: otr-send-symmetric-key-request! state protocol data

This sends a message to the remote party that requests that it uses the extra symmetric key for some out-of-band protocol.

The remote party may ignore this request if the OTR protocol version (as returned by otr-state-version) is not at least 3.

The protocol parameter is an unsigned 32-bit integer that indicates what the key should be used for. At the time this manual is written there are no defined uses. One might expect a list of uses to appear in the protocol documentation at http://www.cypherpunks.ca/otr/.

The data parameter is a bytevector containing protocol-dependent data.

— Procedure: otr-state-symmetric-key state

This returns the extra symmetric key in the form of a 256-bit bytevector.

— Procedure: otr-tag whitespace? versions

Constructs a string that may be sent to a remote party as a request to start an OTR session. New for Industria 1.5.

If whitespace? is true then a whitespace tag will be made. This tag may be appended to a normal message sent by the user. If the recipient's client supports OTR it may start a session, but if it does not support OTR then hopefully it will not show the whitespaces.

The versions argument specifies which OTR protocol versions should be present in the tag. This can either be a list of version numbers or the symbol all.

— Procedure: otr-state-our-instance-tag state

This returns the local instance tag. It is new for Industria 1.5.

It is intended for instance tags to be persistent across client restarts. If the local party crashes then the remote party may still have an OTR session established. If the local client were then to change its instance tag on restart it would not receive any messages from the remote party and would not send error messages. To the remote party it would look like they were being ignored.

Isn't this the most boring manual you've ever read?

Version history:

• Industria 1.5 introduced support for protocol version 3. This new version of the protocol uses instance tags, which are used to distinguish between different OTR sessions. This fixes a problem with chat networks that allow multiple logins. The new version also defines an extra symmetrical key that can be used by out-of-band protocols.

Next: , Previous: net otr, Up: net

#### 2.5.4 Secure Shell (SSH)

The (weinholt net ssh) library hierarchy deals with the Secure Shell protocol. Both SSH servers and clients can be written with these libraries. Some convenient abstractions are currently missing though, e.g. a channel abstraction. These libraries hide the details of the wire protocol and the cryptographic algorithms. The protocol is standardized by a series of RFCs: 4250, 4251, 4252, 4253, 4254, etc.

No TCP server abstraction is provided by Industria. To make a server you will probably need to use your implementation's network abstractions.

It remains to be seen if this interface can be used for interactive applications. One problem is get-ssh, which reads a whole SSH packet. This procedure is blocking. R6RS doesn't provide any procedures for event-driven programming, so the author has made no effort to make this library work in an event-driven setting.

— Parameter: ssh-debugging

This SRFI-39 parameter controls debug output. It is a bit field with three bits currently defined. Bit 0 enables general trace messages, bit 1 enables packet traces and bit 2 enables packet hexdumps.

Default: #b000

— Parameter: ssh-debugging-port

This SRFI-39 parameter controls where debug output is written to. It defaults to the error port that was current when the library top-level was run.

— Parameter: identification-protocol-version

This SRFI-39 parameter is used when constructing the local identification string. It specifies which SSH protocol version number is supported.

Default: "2.0"

— Parameter: identification-software-version

This SRFI-39 parameter is used when constructing the local identification string. It specifies the name and version of the client or server.

Default: "Industria_1"

This SRFI-39 parameter is used when constructing the local identification string. It is #f or optionally a string of comments. This field is sometimes used to identify a vendor.

Default: #f

The following parameters are when constructing the local kex exchange packet. It lists the preferred algorithms. You may remove and reorder the algorithms, but you can't introduce new ones without first adding them to (weinholt net ssh algorithms). The defaults may change in the future.

— Parameter: preferred-kex-algorithms

This is a list of key exchange algorithm names in the order they are preferred.

Default: ("diffie-hellman-group-exchange-sha256" "diffie-hellman-group-exchange-sha1" "diffie-hellman-group14-sha1" "diffie-hellman-group1-sha1")

— Parameter: preferred-server-host-key-algorithms

This is a list of host key algorithm names in the order they are preferred. The server may have more than one host key and this is used to decide between them.

Default: ("ecdsa-sha2-nistp256" "ecdsa-sha2-nistp384" "ecdsa-sha2-nistp521" "ssh-rsa" "ssh-dss")

— Parameter: preferred-encryption-algorithms-client->server

This is a list of encryption algorithm names in the order they are preferred for communication from the client to the server.

Default: ("aes128-ctr" "aes192-ctr" "aes256-ctr" "aes128-cbc" "aes192-cbc" "aes256-cbc" "blowfish-cbc" "arcfour256" "arcfour128" "3des-cbc")

— Parameter: preferred-encryption-algorithms-server->client

This is a list of encryption algorithm names in the order they are preferred for communication from the server to the client.

Default: ("aes128-ctr" "aes192-ctr" "aes256-ctr" "aes128-cbc" "aes192-cbc" "aes256-cbc" "blowfish-cbc" "arcfour256" "arcfour128" "3des-cbc")

— Parameter: preferred-mac-algorithms-client->server

This is a list of message authentication code algorithms in the order they are preferred for communication from the client to the server.

Default: ("hmac-md5" "hmac-sha1" "hmac-sha1-96" "hmac-md5-96")

— Parameter: preferred-mac-algorithms-server->client

This is a list of message authentication code algorithms in the order they are preferred for communication from the server to the client.

Default: ("hmac-md5" "hmac-sha1" "hmac-sha1-96" "hmac-md5-96")

— Parameter: preferred-compression-algorithms-client->server

This is a list of compression algorithms for packets transmitted from the client to the server.

Default: ("none")

— Parameter: preferred-compression-algorithms-server->client

This is a list of compression algorithms for packets transmitted from the server to the client.

Default: ("none")

— Parameter: preferred-languages-client->server

This is currently not used.

Default: ()

— Parameter: preferred-languages-server->client

This is currently not used.

Default: ()

— Procedure: make-ssh-client binary-input-port binary-output-port

Starts an SSH client connection over the two given ports, which should be connected to a server via TCP (or some other similar means).

If everything goes right an ssh-conn object is returned. The peer identification and kexinit fields are valid.

— Procedure: make-ssh-server binary-input-port binary-output-port keys

Starts an SSH server connection over the two given ports, which should be connected to a client via TCP (or some other similar means).

keys is a list of host keys. The currently supported key types are dsa-private-key and ecdsa-sha-2-private-key.

If everything goes right an ssh-conn object is returned. The peer identification and kexinit fields are valid.

— Procedure: ssh-key-exchange ssh-conn

This runs the negotiated key exchange algorithm on ssh-conn. After this is done the client will have received one of the server's public keys. The negotiated encryption and MAC algorithms will have been activated.

— Procedure: ssh-conn-peer-identification ssh-conn

The identification string the peer sent. This is a string that contains the peer's protocol version, software version and optionally some comments.

— Procedure: ssh-conn-peer-kexinit ssh-conn

This is the peer's key exchange initialization (kexinit) packet. It lists the peer's supported algorithms. See net ssh transport.

— Procedure: ssh-conn-host-key ssh-conn

The server's public key. This has unspecified contents before the ssh-key-exchange procedure returns.

— Procedure: ssh-conn-session-id ssh-conn

The session ID of ssh-conn. This has unspecified contents before the ssh-key-exchange procedure returns.

— Procedure: ssh-conn-registrar ssh-conn

Returns a procedure that can be used to register parsers and formatters for SSH packet types. The returned procedure should be given as an argument to register-connection and register-userauth.

— Procedure: ssh-error ssh-conn who message code irritants ...

Sends a disconnect packet to the peer. The packet contains the message and the code. The connection is then closed and an error is raised.

The error code constants are defined elsewhere. See net ssh transport.

— Procedure: put-ssh ssh-conn pkt

Sends the SSH packet pkt to the peer of ssh-conn.

— Procedure: get-ssh ssh-conn

Reads an SSH packet object from the peer of ssh-conn. The end-of-file object will be returned if the peer has closed the connection. The procedure blocks until a message has been received. Any messages of the type ignore are ignored.

Packet types must be registered before they can be received. Initially only the transport layer types are registered. If an unregistered type is received this procedure returns a list of two items: the symbol unimplemented and the unparsed contents of the packet. A packet of type unimplemented is sent to the peer.

— Procedure: close-ssh ssh-conn

Flushes the output port of ssh-conn, and then closes both the input and output ports.

— Procedure: flush-ssh-output ssh-conn

Flushes any pending output on ssh-conn.

The procedures below are used in the implementation of key re-exchange. After the initial key exchange either party can initiate a key re-exchange. RFC 4253 has the following to say on the subject:

It is RECOMMENDED that the keys be changed after each gigabyte of transmitted data or after each hour of connection time, whichever comes sooner. However, since the re-exchange is a public key operation, it requires a fair amount of processing power and should not be performed too often.

The demonstration program secsh-client contains an example of how to initiate key re-exchange. The server demonstration program honingsburk also handles key re-exchange, but does not initiate it. See honingsburk.

— Procedure: build-kexinit-packet ssh-conn

Constructs and returns a key exchange packet for use by the local side.

— Procedure: key-exchange-packet? pkt

Returns #t if pkt should be given to process-key-exchange-packet for handling by the key exchange logic.

— Procedure: ssh-key-re-exchange ssh-conn peer-kex local-kex

Initiates key re-exchange on ssh-conn. This requires the peer's key exchange packet peer-kex, and the local key exchange packet local-kex. The procedure returns before the key re-exchange is finished. Both sides of the algorithm will need to communicate to complete the exchange.

— Procedure: process-key-exchange-packet ssh-conn pkt

Updates the key exchange logic on ssh-conn with the contents of pkt. If the packet is a kexinit packet and ssh-conn is a server, then this will automatically initiate the key re-exchange algorithm.

The procedure may return the symbol finished to indicate that the key exchange algorithm has finished and the new algorithms are used for packets sent to the peer.

Note: This interface is currently balanced in favor of servers. More experience in using the library is needed to determine how to make the key re-exchange interface better for clients. Suggestions are welcome.

Version history:

• (1 0) – Initial version.

Next: , Up: net ssh
##### 2.5.4.1 Secure Shell Connection Protocol

The (weinholt net ssh connection) library implements record types, parsers and formatters for the connection protocol packets in SSH.

The connection protocol handles two types of communication: global requests and channels. The global requests can be used to setup TCP/IP port forwarding. Most communication over SSH passes through channels. Channels are opened with the channel-open requests. The client and the server each assign an ID number to a channel: one ID is sent in the channel-open packet, the other ID in the channel-open-confirmation packet. In Industria all packets that are directed to a specific channel inherit from the channel-packet record type and the ID can be found with the channel-packet-recipient procedure.

Strings and bytevectors may be used interchangeably when constructing packets. Strings will automatically be converted with string->utf8. When these packets are received the parser will either parse those fields either as a string or a bytevector. A bytevector will be used when the field can contain more or less arbitrary data, e.g. filenames.

The text of this section uses the words “packet”, “message” and “request” interchangeably.

See RFC 4254 for a more detailed description of this protocol.

— Procedure: register-connection registrar

Registers the packet types for the connection protocol so that they may be received and sent. A registrar may be obtained from an ssh-conn object using ssh-conn-registrar.

Constructs a global request: a connection request not related to any channel. Some global requests contain additional fields. These requests are represented by the global-request/* packets.

— Procedure: global-request? obj

Returns true if obj is a global-request? packet.

— Procedure: global-request-type pkt

This field contains a string identifying the type of the request, e.g. "no-more-sessions@openssh.com".

This field is true if the sender expects a request-success or request-failure record in response.

Constructs a request that instructs the server to bind a TCP server port and forward connections to the client.

— Procedure: global-request/tcpip-forward? obj

Returns true if obj is a global-request/tcpip-forward packet.

This field is a string that represents the address to which the server should bind the TCP server port. Some addresses are given special meaning:

""
The server should listen to all its addresses on all supported protocols (IPv4, IPV6, etc).
"0.0.0.0"
The server should listen to all its IPv4 addresses.
"::"
The server should listen to all its IPv6 addresses.
"localhost"
The server should listen to its loopback addresses on all supported protocols.
"127.0.0.1"
The server should listen to its IPv4 loopback address.
"::1"
The server should listen to its IPv6 loopback address.

— Procedure: global-request/tcpip-forward-port req

This field is an integer representing the port number to which the server should bind the TCP server port. If the number is 0 and want-reply? is true, the server will pick a port number and send it to the client in a request-success packet (the port number can be recovered with (unpack "!L" (request-success-data response))).

Constructs a message that undoes the effect of a global-request/tcpip-forward request.

— Procedure: global-request/cancel-tcpip-forward? obj

Returns true if obj is a global-request/cancel-tcpip-forward packet.

See global-request/tcpip-forward-address.

— Procedure: global-request/cancel-tcpip-forward-port req

See global-request/tcpip-forward-port.

— Procedure: make-request-success data

Constructs a packet which indicates that the previous global-request was successful.

— Procedure: request-success? obj

Returns true if obj is a request-success packet.

— Procedure: request-success-data pkt

This field contains a request-specific bytevector which is mostly empty.

— Procedure: make-request-failure

Returns an object which indicates that a global request failed.

— Procedure: request-failure? obj

Returns true if obj is a request-failure packet.

All requests to open a channel are represented by channel-open/* packets.

— Procedure: channel-open? obj

Returns true if obj is a channel-open packet.

— Procedure: channel-open-type pkt

A string representing the type of the channel-open request, e.g. "session".

— Procedure: channel-open-sender pkt

This is the ID for the sender side of the channel.

— Procedure: channel-open-initial-window-size pkt

This is the window size of the channel. The window size is used for flow-control and it decreases when data is sent over the channel and increases when a channel-window-adjust packet is sent. Each side of a channel has a window size.

— Procedure: channel-open-maximum-packet-size pkt

This is the maximum allowed packet size for data sent to a channel. It basically limits the size of channel-data and channel-extended-data packets.

Constructs a request to open a new channel which is then connected to a TCP port.

— Procedure: channel-open/direct-tcpip? obj

Returns true if obj is a channel-open/direct-tcpip packet.

This is the hostname or network address that the TCP connection should be connected to.

— Procedure: channel-open/direct-tcpip-connect-port pkt

This is the port number that the TCP connection should be connected to.

This is the network address of the machine that made the request.

— Procedure: channel-open/direct-tcpip-originator-port pkt

This is the port number on which the request was made. This is useful when a client implements forwarding of client-local TCP ports.

This request is used by the server to tell the client that a TCP connection has been requested to a port for which the client sent a global-request/tcpip-forward request.

— Procedure: channel-open/forwarded-tcpip? obj

Returns true if obj is a channel-open/forwarded-tcpip packet.

— Procedure: channel-open/forwarded-tcpip-connected-port pkt

The port to which the TCP connection was made.

The remote address of the TCP connection.

— Procedure: channel-open/forwarded-tcpip-originator-port pkt

The remote port of the TCP connection.

— Procedure: make-channel-open/session sender-id initial-window-size maximum-packet-size

Construct a request to open a session channel. This type of channel is used for interactive logins, remote command execution, etc. After the channel has been established the client will send e.g. a channel-request/shell or a channel-request/exec request.

— Procedure: channel-open/session? obj

Returns true if obj is a channel-open/session packet.

— Procedure: make-channel-open/x11 type sender-id initial-window-size maximum-packet-size originator-address originator-port

Constructs a message that opens an X11 channel. This message can be sent after X11 forwarding has been requested.

— Procedure: channel-open/x11? obj

Returns true if obj is a channel-open/x11 packet.

The network address that originated the X11 connection.

— Procedure: channel-open/x11-originator-port pkt

The network port that originated the X11 connection.

— Procedure: channel-packet? obj

Returns true if obj is a channel-packet packet.

— Procedure: channel-packet-recipient pkt

This field is an integer that identifies the ID of the channel that should receive the request.

— Procedure: make-channel-open-failure recipient reason-code description language

Constructs a packet that represents a failure to open a channel. It is sent in response to a channel-open/* request.

— Procedure: channel-open-failure? obj

Returns true if obj is a channel-open-failure packet.

— Procedure: channel-open-failure-reason-code pkt
SSH-OPEN-ADMINISTRATIVELY-PROHIBITED
SSH-OPEN-CONNECT-FAILED
SSH-OPEN-UNKNOWN-CHANNEL-TYPE
SSH-OPEN-RESOURCE-SHORTAGE

— Procedure: channel-open-failure-description pkt

This field is a human-readable reason for why the channel could not be opened.

— Procedure: channel-open-failure-language pkt

This field is most commonly unused and set to "".

— Procedure: make-channel-open-confirmation recipient sender initial-window-size maximum-packet-size

Constructs a message that indicates a channel was successfully opened (identified by recipient). The party that sends this message will include its own channel ID (sender).

— Procedure: channel-open-confirmation? obj

Returns true if obj is a channel-open-confirmation packet.

— Procedure: channel-open-confirmation-sender pkt

This field contains the sender's ID for this channel.

— Procedure: channel-open-confirmation-initial-window-size pkt

This is the sender's initial window size. Analogous to the initial window size in a channel-open/* request.

— Procedure: channel-open-confirmation-maximum-packet-size pkt

This is the sender's maximum packet size. Analogous to the maximum packet size in a channel-open/* request.

This constructs a packet that is used to increment the window size of channel recipient by amount octets. It tells the remote part that the channel may receive additional data. If the client has assigned to a channel a receive buffer of 4096 bytes and the server sends 4096 bytes, the server will not be able to successfully send more data until the client has processed some of the buffer. When there is more room in the buffer the client can send a message of this type.

Returns true if obj is a channel-window-adjust packet.

This field contains the number of bytes that will be added to the window size.

— Procedure: make-channel-data recipient value

This constructs a request that sends data over a channel.

— Procedure: channel-data? obj

Returns true if obj is a channel-data packet.

— Procedure: channel-data-value pkt

This field contains a bytevector with data being sent over the channel.

— Procedure: make-channel-extended-data recipient type value

This constructs a message that works just like channel-data, except it contains an additional type field (explained below).

— Procedure: channel-extended-data? obj

Returns true if obj is a channel-extended-data packet.

— Procedure: channel-extended-data-type pkt

Data sent by a channel-data packet will normally be sent to a port connected with standard output. A channel-extended-data field is used when the data destination is a different port.

SSH-EXTENDED-DATA-STDERR
This constant specifies that the destination is the standard error port.

— Procedure: channel-extended-data-value pkt

This field contains a bytevector with the data sent over the channel, e.g. an error message printed on the standard error port.

— Procedure: make-channel-eof recipient

This constructs a packet that signals the end-of-file condition on the channel identified by the recipient ID.

— Procedure: channel-eof? obj

Returns true if obj is a channel-eof packet.

— Procedure: make-channel-close recipient

This constructs a message that is used when a channel is closed.

— Procedure: channel-close? obj

Returns true if obj is a channel-close packet.

— Procedure: make-channel-success recipient

This constructs a packet that indicates that the previous request was successful. These packets are sent in response to requests where want-reply? is true.

— Procedure: channel-success? obj

Returns true if obj is a channel-success packet.

— Procedure: make-channel-failure recipient

This constructs a packet that indicates that the previous request was not successful. These packets are sent in response to requests where want-reply? is true.

— Procedure: channel-failure? obj

Returns true if obj is a channel-failure packet.

— Procedure: channel-request? obj

Returns true if obj is a channel-request packet.

— Procedure: channel-request-type req

This field is a string that identifies the type of the request, e.g. "break" or "shell".

When this field is true the peer will respond with channel-success or channel-failure. This field is not valid for all requests. Where it is not valid the constructor will not include it as an argument.

— Procedure: make-channel-request/break recipient want-reply? length

This constructs a request that relays a “BREAK” signal on the channel. A “BREAK” is a signalling mechanism used with serial consoles. This request is standardized by RFC 4335.

— Procedure: channel-request/break? obj

Returns true if obj is a channel-request/break packet.

— Procedure: channel-request/break-length req

The length of the signal in milliseconds.

— Procedure: make-channel-request/env recipient want-reply? name value

Constructs a request that can be used before a shell or command has been started. It is used to set an environment variable (of the same kind that SRFI-98 accesses).

— Procedure: channel-request/env? obj

Returns true if obj is a channel-request/env packet.

— Procedure: channel-request/env-name req

This is a string that identifies the name of the environment variable.

— Procedure: channel-request/env-value req

This is a bytevector that contains the value of the environment variable.

— Procedure: make-channel-request/exec recipient want-reply? command

Constructs a request that instructs the server to execute a command. The channel identified by recipient will be connected to the standard input and output ports of the program started by the server.

— Procedure: channel-request/exec? obj

Returns true if obj is a channel-request/exec packet.

— Procedure: channel-request/exec-command req

This field is a bytevector that contains the command that the server should try to execute.

— Procedure: make-channel-request/exit-signal recipient name core-dumped? message language

This constructs a packet which indicates that the program connected to the channel identified by recipient has exited due to an operating system signal.

— Procedure: channel-request/exit-signal? obj

Returns true if obj is a channel-request/exit-signal packet.

— Procedure: channel-request/exit-signal-name req

This is a string that identifies the signal by name. For posix systems it is one of the following: "ABRT", "ALRM", "FPE", "HUP", "ILL", "INT", "KILL", "PIPE", "QUIT", "SEGV", "TERM", "USR1", "USR2". Other signal names may be used by following the guidelines in section 6.10 of RFC 4254.

— Procedure: channel-request/exit-signal-core-dumped? req

This field is true when the operating system saved a process image (“core dump”) when it sent the signal.

— Procedure: channel-request/exit-signal-message req

This may be a string that explains the signal.

— Procedure: channel-request/exit-signal-language req

This string may identify the language used in channel-request/exit-signal-message.

— Procedure: make-channel-request/exit-status recipient value

This constructs a packet which indicates that the program connected to the channel identified by recipient has exited voluntarily.

— Procedure: channel-request/exit-status? obj

Returns true if obj is a channel-request/exit-status packet.

— Procedure: channel-request/exit-status-value req

This is an integer that identifies the exit status of the program. It is the same kind of number used by the the Scheme procedure exit.

— Procedure: make-channel-request/pty-req recipient want-reply? term columns rows width height modes

Constructs a request that instructs the server to allocate a pseudo-terminal (PTY) for the channel identified by recipient. A PTY is needed for interactive programs, such as shells and Emacs.

— Procedure: channel-request/pty-req? obj

Returns true if obj is a channel-request/pty-req packet.

— Procedure: channel-request/pty-req-term req

This is a string that identifies the type of terminal that this PTY will be connected to. If the terminal is compatible with the DEC VT100 the value would be "vt100". This value is also the environment variable TERM. The set of supported terminal types depends on the server. Typically the software running on an SSH server uses the “terminfo” database.

— Procedure: channel-request/pty-req-columns req

This field contains the number of columns the terminal supports, e.g. 80. The channel-request/window-change request can be used to update this value if the terminal supports resizing.

— Procedure: channel-request/pty-req-rows req

This field contains the number of rows the terminal supports, e.g. 24.

— Procedure: channel-request/pty-req-width req

This field specifies the width of the terminal in pixels.

— Procedure: channel-request/pty-req-height req

This field specifies the height of the terminal in pixels.

— Procedure: channel-request/pty-req-modes req

This is a bytevector that encodes POSIX terminal modes. Unlike the size of the terminal, it is not possible to change the modes after the PTY has been created. The client should emulate a terminal set to “raw” mode and send a correct list of terminal modes. The server will then cooperate to handle the rest. This means that, unlike with telnet, the client will generally not do local “canonical” terminal processing.

— Procedure: bytevector->terminal-modes bv

Decodes the modes from a channel-request/pty-req. The return value is an association list.

— Procedure: terminal-modes->bytevector modes

The inverse of bytevector->terminal-modes. All modes specified by RFC 4254 can be encoded.

          (import (weinholt net ssh connection))
(terminal-modes->bytevector '((VINTR . 3) (VERASE . 127)))
⇒ #vu8(1 0 0 0 3 3 0 0 0 127 0)


Constructs a request that starts a login shell on the channel identified by recipient. Normally a PTY must first have been connected to the channel.

— Procedure: channel-request/shell? obj

Returns true if obj is a channel-request/shell packet.

— Procedure: make-channel-request/signal recipient name

Construct a packet that sends a signal to the program connected to the channel identified by recipient.

— Procedure: channel-request/signal? obj

Returns true if obj is a channel-request/signal packet.

— Procedure: channel-request/signal-name req

This field contains a signal name of the same type as that used by channel-request/exit-signal.

— Procedure: make-channel-request/subsystem recipient want-reply? name

Constructs a request that a subsystem should be connected to the channel identified by recipient.

— Procedure: channel-request/subsystem? obj

Returns true if obj is a channel-request/subsystem packet.

— Procedure: channel-request/subsystem-name req

This field identifies the subsystem being requested, e.g. "sftp".

— Procedure: make-channel-request/window-change recipient columns rows width height

Construct a message that tells the server that the terminal window associated with a channel has been resized. The channel should have a PTY (see channel-request/pty-req).

— Procedure: channel-request/window-change? obj

Returns true if obj is a channel-request/window-change packet.

— Procedure: channel-request/window-change-columns req

Contains the new character cell width of the terminal window.

— Procedure: channel-request/window-change-rows req

Contains the new character cell height of the terminal window.

— Procedure: channel-request/window-change-width req

Contains the new pixel width of the terminal window.

— Procedure: channel-request/window-change-height req

Contains the new pixel height of the terminal window.

Constructs an X11 (X Window System) forwarding request.

— Procedure: channel-request/x11-req? obj

Returns true if obj is a channel-request/x11-req packet.

— Procedure: channel-request/x11-req-single-connection? req

If this field is true when only one X11 connection should be forwarded.

— Procedure: channel-request/x11-req-protocol req

This field identifies an X11 authentication protocol. The most common value is "MIT-MAGIC-COOKIE-1".

This is a “magic cookie” encoded as a hexadecimal string. It is used with "MIT-MAGIC-COOKIE-1". It is recommended by RFC 4254 that this cookie should be different from the actual cookie used by the X11 server. When receiving a channel-open/x11 request the cookie can be intercepted, verified and replaced with the real one.

— Procedure: channel-request/x11-req-screen req

An X11 display can have, in X jargon, multiple screens. Normally this field would be 0.

— Procedure: make-channel-request/xon-xoff recipient client-can-do?

Constructs a message that tells the client when it can do local processing of terminal flow control (C-s and C-q).

— Procedure: channel-request/xon-xoff? obj

Returns true if obj is a channel-request/xon-xoff packet.

— Procedure: channel-request/xon-xoff-client-can-do? req

This flag is true if the client is allowed to do local processing of terminal flow control. If the flag is false then flow control is done on the server.

Version history:

• (1 0) – Initial version.

Next: , Previous: net ssh connection, Up: net ssh
##### 2.5.4.2 Secure Shell Transport Layer Protocol

The (weinholt net ssh transport) library implements record types, parsers and formatters for the transport layer packets in SSH.

See RFC 4253 for a description of this protocol.

— Procedure: register-transport registrar

Registers the packet types for the transport layer so that they may be received and sent. A registrar may be obtained using ssh-conn-registrar.

— Procedure: make-disconnect code message language

Constructs a packet that closes the SSH connection. After sending or receiving this message the connection should be closed with close-ssh. The ssh-error procedure may be more convenient than manually constructing and sending a disconnect packet.

— Procedure: disconnect? obj

Returns #t if obj is a disconnect packet.

— Procedure: disconnect-code pkt

This field is an integer that represents the cause of the disconnect. The reason could be one of these (exported) constants:

SSH-DISCONNECT-HOST-NOT-ALLOWED-TO-CONNECT
SSH-DISCONNECT-PROTOCOL-ERROR
SSH-DISCONNECT-KEY-EXCHANGE-FAILED
SSH-DISCONNECT-RESERVED
SSH-DISCONNECT-MAC-ERROR
SSH-DISCONNECT-COMPRESSION-ERROR
SSH-DISCONNECT-SERVICE-NOT-AVAILABLE
SSH-DISCONNECT-PROTOCOL-VERSION-NOT-SUPPORTED
SSH-DISCONNECT-HOST-KEY-NOT-VERIFIABLE
SSH-DISCONNECT-CONNECTION-LOST
SSH-DISCONNECT-BY-APPLICATION
SSH-DISCONNECT-TOO-MANY-CONNECTIONS
SSH-DISCONNECT-AUTH-CANCELLED-BY-USER
SSH-DISCONNECT-NO-MORE-AUTH-METHODS-AVAILABLE
SSH-DISCONNECT-ILLEGAL-USER-NAME

— Procedure: disconnect-message pkt

This is a human-readable explanation for the disconnect.

— Procedure: disconnect-language pkt

Most commonly unused, "".

— Procedure: make-ignore data

Construct a new ignore packet using the bytevector data as the payload. These packets are ignored by receivers but can be used to make traffic analysis more difficult.

— Procedure: ignore? obj

Returns #t if obj is an ignore packet.

— Procedure: make-unimplemented sequence-number

This constructs a message that should be sent when a received packet type is not implemented.

— Procedure: unimplemented? obj

Returns #t if obj is an unimplemented packet.

— Procedure: unimplemented-sequence-number pkt

Each packet sent over an SSH connection is given an implicit sequence number. This field exactly identifies one SSH packet.

— Procedure: make-debug always-display? message language

Constructs a debug packet. It contains a message that a client or server may optionally display to the user.

— Procedure: debug? obj

Returns #t if obj is a debug packet.

— Procedure: debug-always-display? pkt

If this field is true then the message should be displayed.

— Procedure: debug-message pkt

This is a string containing the debugging message. If it is displayed to the user it should first be filtered.

— Procedure: debug-language pkt

Most commonly unused, "".

— Procedure: make-service-request name

This constructs a service request packet. The first service requested is normally "ssh-userauth". See net ssh userauth.

— Procedure: service-request? obj

Returns #t if obj is a service-request packet.

— Procedure: service-request-name pkt

This is the name of the service being requested, e.g. "ssh-userauth".

— Procedure: make-service-accept name

Constructs a request which indicates that access to a requested service was granted.

— Procedure: service-accept? obj

Returns #t if obj is a service-accept packet.

— Procedure: service-accept-name pkt

This field contains the name of the service to which access was granted.

— Procedure: make-kexinit cookie kex-algorithms server-host-key-algorithms encryption-algorithms-client-to-server encryption-algorithms-server-to-client mac-algorithms-client-to-server mac-algorithms-server-to-client compression-algorithms-client-to-server compression-algorithms-server-to-client languages-client-to-server languages-server-to-client first-kex-packet-follows? reserved

Constructs a kexinit packet, which is used as part of the key exchange algorithm. The arguments are explained below. You probably want to use build-kexinit-packet instead of this procedure.

— Procedure: kexinit? obj

Returns #t if obj is a kexinit packet.

This field is a random bytevector. It is used in the key exchange to make things more difficult for an attacker.

— Procedure: kexinit-kex-algorithms pkt

A list of the supported key exchange algorithms (mostly variations on Diffie-Hellman).

— Procedure: kexinit-server-host-key-algorithms pkt

A list of the supported host key algorithms.

— Procedure: kexinit-encryption-algorithms-client-to-server pkt

A list of the supported encryption algorithms for packets sent from the client to the server.

— Procedure: kexinit-encryption-algorithms-server-to-client pkt

A list of the supported encryption algorithms for packets sent from the server to the client.

— Procedure: kexinit-mac-algorithms-client-to-server pkt

A list of the supported Message Authentication Code (MAC) algorithms for packets sent from the client to the server.

— Procedure: kexinit-mac-algorithms-server-to-client pkt

A list of the supported Message Authentication Code (MAC) algorithms for packets sent from the server to the client.

— Procedure: kexinit-compression-algorithms-client-to-server pkt

A list of the supported compression algorithms for packets sent from the client to the server. The algorithm "none" is currently the only implemented compression algorithm.

— Procedure: kexinit-compression-algorithms-server-to-client pkt

A list of the supported compression algorithms for packets sent from the server to the client. The algorithm "none" is currently the only implemented compression algorithm.

— Procedure: kexinit-languages-client-to-server pkt

Normally never used. Set to the empty list.

— Procedure: kexinit-languages-server-to-client pkt

Normally never used. Set to the empty list.

— Procedure: kexinit-first-kex-packet-follows? pkt

If this field is true then the server and client will try to cooperate in order to make the key exchange run faster over connections with high latency. This optimization only works when the server and client both prefer the same algorithms.

— Procedure: kexinit-reserved pkt

This field must be zero.

— Procedure: make-newkeys

Constructs a new newkeys packet. This message is used as part of key exchange to notify the remote side that new encryption keys are being used.

— Procedure: newkeys? obj

Returns #t if obj is a newkeys packet.

Version history:

• (1 0) – Initial version.

Previous: net ssh transport, Up: net ssh
##### 2.5.4.3 Secure Shell Authentication Protocol

The (weinholt net ssh userauth) library implements record types, parsers and formatters for the authentication protocol packets in SSH.

See RFC 4252 for a more detailed description of this protocol. In this protocol the client sends packets of type userauth-request. The type names that start with userauth-request/ are sub-types that contain user credentials. All other packet types documented here are sent by the server.

All user authentication requests contain a user name, a service name and a method name. The service name most commonly used is "ssh-connection", which requests access to the connection protocol. See net ssh connection.

— Procedure: register-userauth registrar

Registers the packet types for the authentication protocol so that they may be received and sent. A registrar may be obtained using ssh-conn-registrar.

Registers the packet types for the password authentication protocol. This is a supplement to register-userauth.

— Procedure: register-userauth-public-key registrar

Registers the packet types for the public key authentication protocol. This is a supplement to register-userauth.

— Procedure: deregister-userauth registrar

Deregisters all authentication protocol packet types.

— Procedure: make-userauth-request username service method

Constructs a new user authentication request. This particular procedure is only good for constructing requests that use the "none" method. When such a request is sent to the server it will respond with a list of available authentication methods. To make a proper request use one of the make-userauth-request/* procedures below. Those procedures automatically include the correct method in the request. The service is normally "ssh-connection". See net ssh connection.

— Procedure: userauth-request? obj

Returns true if obj is a userauth-request packet. This includes userauth-request/password packets, and so on.

This returns the user name field of request.

— Procedure: userauth-request-service request

This returns the service name field of request.

— Procedure: userauth-request-method request

This returns the method name field of request. Examples include "none", "password" and "publickey".

If the server does not like the credentials provided in a userauth-request it will send a userauth-failure packet.

— Procedure: make-userauth-failure can-continue partial?

Constructs a message that indicates to the client that the user authentication request was not successful.

— Procedure: userauth-failure? obj

Returns true if obj is a userauth-failure packet. These packets indicate the the client was denied access to the requested service. The credentials might be incorrect or the server might be requesting additional authentication requests (see below).

— Procedure: userauth-failure-can-continue failure

This returns a list of authentication methods that “can continue”, i.e. methods that might be successful given that correct credentials are provided.

— Procedure: userauth-failure-partial? failure

This is a boolean that indicates partial success. The server might require multiple successful authentication requests (see RFC 4252).

— Procedure: make-userauth-success

Constructs a packet that indicates to the client that the user authentication was successful. The client can now use the requested service (e.g. the connection protocol). This message has no fields.

— Procedure: userauth-success? obj

Returns true if obj is a userauth-success packet.

The server can send a banner before the user authenticates. The banner might often contain a warning about unauthorized access.

— Procedure: make-userauth-banner message language

This constructs a textual message that the server can send to the client. The client software can then display it to the user. This happens before user authentication is attempted and often contains a warning about unauthorized accesss.

— Procedure: userauth-banner? obj

Returns true if obj is a userauth-banner packet.

— Procedure: userauth-banner-message banner

This field is a message that the client can show to the user.

— Procedure: userauth-banner-language banner

This field might indicate the language of the text in the banner, but is most commonly empty and not used.

The client can try to authenticate with a password. Note that the unencrypted password is seen by the server. It's important to check hosts keys to make sure you're connecting to the right server.

Constructs a user authentication request. This is a normal attempt to login with a user name and password. There is an alternative protocol for these types of login requests: the "keyboard-interactive" method (support is planned).

Returns true if obj is a userauth-request/password packet.

Returns the password field for this user authentication request.

The server can request that the client should change its password.

This constructs a password change request. Some servers might send this packet if e.g. they use a password expiry system.

Returns true if obj is a userauth-request/changereq packet.

This is the message to show the user when prompting for the new password.

This is the language used in the password change request prompt.

After having received a request to change its password a client may send a userauth-request/password-change packet.

Constructs a request to authenticate the user and at the same time change the user's password. This message may be sent without having received a userauth-request/changereq packet. Please see section 8 of RFC 4252 for the meaning of the packet that the server will send in response to this packet.

Returns true if obj is a userauth-request/password-change packet.

This field contains the user's current password.

This field contains the user's new password.

— Procedure: make-userauth-request/public-key-query username service key

Before performing a potentially expensive private key operation the client may ask the server if a specific key might be used to authenticate.

— Procedure: userauth-request/public-key-query? obj

Returns true if obj is a userauth-request/public-key-query packet.

— Procedure: userauth-request/public-key-query-algorithm request

This field is automatically filled in by make-userauth-request/public-key-query to contain the public key algorithm name of the key contained in the query.

— Procedure: userauth-request/public-key-query-key request

This field contains an SSH public key.

— Procedure: make-userauth-public-key-ok algorithm key

The server sends userauth-public-key-ok to indicate that the user may try to authenticate with the given key.

— Procedure: userauth-public-key-ok? obj

Returns true if obj is a userauth-public-key-ok packet.

— Procedure: userauth-public-key-ok-algorithm request

This is a copy of the algorithm name contained in the userauth-request/public-key-query packet.

— Procedure: userauth-public-key-ok-key request

This is a copy of the public key contained in the userauth-request/public-key-query packet.

— Procedure: make-userauth-request/public-key username service public-key

This procedure creates an unsigned request to authenticate with public key cryptography. The client may try to authenticate itself by sending a signed request to the server. The server will have a copy of the public key on file, e.g. stored in the user's authorized_keys file. By using the public key it can confirm that the client is possession of the corresponding private key. The packet returned by this procedure may be signed with sign-userauth-request/public-key.

— Procedure: userauth-request/public-key? obj

Returns true if obj is a userauth-request/public-key packet.

— Procedure: userauth-request/public-key-algorithm request

This field indicates the public key algorithm name of the public key in the request. It is automatically filled in when the request is constructed.

— Procedure: userauth-request/public-key-key request

This field contains an SSH public key object. See crypto ssh-public-key.

— Procedure: sign-userauth-request/public-key request session-id private-key

This generates a signed userauth-request/public-key packet. It needs an unsigned request, which may be created with make-userauth-request/public-key. The session-id can be recovered with ssh-conn-session-id. The private-key must be a private DSA or ECDSA key (support for RSA signing is planned). The signed request uses the SSH connection's session ID and can therefore not be used with any other connection.

Version history:

• (1 0) – Initial version.

Next: , Previous: net ssh, Up: net

#### 2.5.5 Basic TCP client connections

The (weinholt net tcp) provides a simple TCP client. This library needs implementation-specific code, so the author is not eager to provide more than the bare minimum.

This library should work with Ikarus Scheme, GNU Guile, Larceny (not tested with Petit Larceny and Common Larceny), Mosh Scheme, Petite Chez Scheme (as long as the nc command is installed), Vicare Scheme, and Ypsilon Scheme. Once upon a time it also worked with PLT Scheme, but it has not been tested with Racket.

— Procedure: tcp-connect hostname portname

Initiates a TCP connection to the given hostname and portname (both of which are strings).

Returns an input-port and an output-port. They are not guaranteed to be distinct.

Version history:

• (0 0) – Initial version.

Previous: net tcp, Up: net

#### 2.5.6 Transport Layer Security (simple interface)

The (weinholt net tls simple) library provides custom binary ports that implement the Transport Layer Security (TLS) protocol used by e.g. https. After starting TLS you can use the new ports as easily as if they were unencrypted. TLS encrypts the traffic and lets you verify the remote server's identity. This library currently only provides a TLS client. Both TLS 1.0 and TLS 1.1 are supported. The RSA, DHE-RSA (Ephemeral Diffie-Hellman) and DHE-DSA key exchange algorithms are supported, as well as AES, ARCFOUR and 3DES ciphers.

This whole thing is kind of experimental and I'd appreciate feedback.

— Procedure: tls-connect hostname portname [client-certificates]

Initiates a TCP connection to the given hostname and portname (which are strings) and negotiates a TLS connection. Can hang forever.

Pay no attention to the optional client-certificates argument. It is not yet implemented.

This procedure returns three values: a binary input port, a binary output port, and a TLS connection object. The last value comes from the not-yet-documented (weinholt net tls) library. It is intended to be used to access the server's certificate chain, which can be verified using the not-yet-documented (weinholt crypto x509) library.

— Procedure: start-tls hostname portname binary-input-port binary-output-port [client-certificates]

Negotiates TLS on two already opened ports. Same return values as tls-connect. This procedure can be used for protocols where the communication at first is in plaintext and then switches over to encrypted (i.e. STARTTLS). Some such protocols are SMTP, LDAP and XMPP.

Version history:

• (1 0) – Initial version. Very slow indeed, but it works.

Next: , Previous: net, Up: Library reference

### 2.6 Binary structure utilities

Up: struct

#### 2.6.1 Binary structure packing and unpacking

With (weinholt struct pack) you can easily access fields in a bytevector and make new bytevectors from fields. The library defines syntax that is similar to Python's struct module or Perl's pack/unpack functions.

The exported bindings are actually syntax, but they can be used as normal procedures, thanks to the use of make-variable-transformer. The syntax transformers basically perform inlining.

This library uses format strings which specify binary fields. The format strings are read left-to-right and their syntax is:

• c – s8, a signed byte.
• C – u8, an unsigned byte.
• s – s16, a signed 16-bit word.
• S – u16, an unsigned 16-bit word.
• l – s32, a signed 32-bit word.
• L – u32, an unsigned 32-bit word.
• q – s64, a signed 64-bit word.
• Q – u64, an unsigned 64-bit word.
• f – an IEEE-754 single-precision number.
• d – an IEEE-754 double-precision number.
• x – one byte of padding (zero).
• a – enable automatic natural alignment (default). Padding is inserted to align fields to their natural alignment, i.e. a 32-bit field is aligned to a 4 byte offset.
• u – disable automatic natural alignment.
• ! and > – the following fields will have big-endian (network) byte order.
• < – the following fields will have little-endian byte order.
• = – the following fields will have native endianness.
• whitespace – ignored.
• decimals – repeat the following format character N times.
— Procedure: unpack fmt bytevector [offset]

Returns as many values as there are fields in the fmt string. The values are fetched from the bytevector starting at the offset (by default 0). For example, if the format string is "C", this translates into a bytevector-u8-ref call.

          (import (weinholt struct pack))
(unpack "!xd" (pack "!xd" 3.14))
⇒ 3.14

          (number->string (unpack "!L" #vu8(#x00 #xFB #x42 #xE3)) 16)
⇒ "FB42E3"

          (unpack "!2CS" #vu8(1 2 0 3))
⇒ 1
⇒ 2
⇒ 3

— Procedure: pack fmt values ...

Returns a new bytevector containing the values encoded as per the fmt string.

          (pack "!CCS" 1 2 3)
⇒ #vu8(1 2 0 3)

          (pack "!CSC" 1 2 3)
⇒ #vu8(1 0 0 2 3)

          (pack "!SS" (question-qtype x) (question-qclass x))
==>
(let ((bv (make-bytevector 4)))
(pack! "!SS" bv 0 (question-qtype x) (question-qclass x))
bv)
==>
(let ((bv (make-bytevector 4)))
(let ((bv bv) (off 0))
(bytevector-u16-set! bv 0 (question-qtype x)
(endianness big))
(bytevector-u16-set! bv 2 (question-qclass x)
(endianness big))
(values))
bv)

— Procedure: pack! fmt bytevector offset values ...

The same as pack, except it modifies the given bytevector and returns no values.

— Procedure: get-unpack binary-input-port fmt

Reads (format-size fmt) bytes from the binary-input-port and unpacks them according to the format string. Returns the same values as unpack would.

          (get-unpack port "4xCCxCC7x")
==>
(let ((bv (get-bytevector-n port 16))
(off 0))
(values (bytevector-u8-ref bv 4) (bytevector-u8-ref bv 5)
(bytevector-u8-ref bv 7) (bytevector-u8-ref bv 8)))

— Procedure: format-size fmt

Returns how many bytes the fields in the format string would use if packed together, including any padding.

          (format-size "!xQ")
⇒ 16

          (format-size "!uxQ")
⇒ 9


Version history:

• (1 0) – Initial version.
• (1 1)unpack can now be used as a procedure.
• (1 2) – Added the format characters a and u.
• (1 3) – Added get-unpack. Removed the unnecessary size check in unpack.
• (1 4)pack, get-unpack and format-size are now syntax. The unpack syntax can handle non-constant offsets. Removed another unnecessary size check in pack!. Added documentation and examples.

Next: , Previous: struct, Up: Library reference

### 2.7 Textual structure utilities

Next: , Up: text

#### 2.7.1 Base64 encoding and decoding

The (weinholt text base64) library provides procedures for dealing with the standard Base64 encoding from RFC 4648 and some variations thereof. The Base64 encoding can be used to represent arbitrary bytevectors purely in printable ASCII.

One variation of Base64 is in the alphabet used. The standard encoding uses an alphabet that ends with #\+ and #\/, but these characters are reserved in some applications. One such application is HTTP URLs, so there is a special encoding called base64url that simply uses a different alphabet.

The line length can also vary. Some applications will need Base64 encoded strings that have no line endings at all, while other applications have 64 or 76 characters per line. For these uses the line length must be a multiple of four characters. Sometimes there is not enough input to get a multiple of four, but then the padding character #\= is used. Some applications don't use padding.

Some applications have their own “Base64” encodings that encode bits in a different order. Such will be deemed magic and shall not work with this library.

— Procedure: base64-encode bv [start end line-length no-padding alphabet port]

Encodes the bytevector bv in Base64 encoding. Optionally a range of bytes can be specified with start and end.

If a maximum line length is required, set line-length to an integer multiple of four (the default is #f). To omit padding at the end of the data, set no-padding or a non-false value. The alphabet is a string of length 64 (by default base64-alphabet).

The port is either a textual output port or #f, in which case this procedure returns a string.

— Procedure: base64-decode str [alphabet port]

Decodes the Base64 data in str. The string has to contain pure Base64 data, including padding, and no whitespace or other extra characters. The output is written to the binary output port. Returns a bytevector if port is #f.

— Procedure: put-delimited-base64 port type bv [line-length]

Write the Base64 encoding of bv to the port. The output is delimited by BEGIN/END lines that include the type.

          (import (weinholt text base64))
(put-delimited-base64 (current-output-port) "EXAMPLE"
(string->utf8 "POKEY THE PENGUIN"))
-| -----BEGIN EXAMPLE-----
-| UE9LRVkgVEhFIFBFTkdVSU4=
-| -----END EXAMPLE-----

— Procedure: get-delimited-base64 port

Reads a delimited Base64 encoded bytevector and returns two values: type (a string) and data (a bytevector). The data value is the end-of-file object if port-eof? would return #t.

Note: This procedure ignores MIME headers. Some delimited Base64 formats have headers on the line after BEGIN, followed by an empty line.

Note: This procedure ignores the Radix-64 checksum. The Radix-64 format (RFC 4880) is based on Base64, but appends a CRC-24 (prefixed by #\=) at the end of the data.

The rationale for ignoring headers and checksums is that it follows the Principle of Robustness: “Be conservative in what you send; be liberal in what you accept from others.” Lines before the BEGIN line are also ignored, because some applications (like OpenSSL) like to prepend a human readable version of the data.

You should probably use special parsers if you are reading data with headers or checksums. For some applications, e.g. MIME, you might need a Base64 decoder that also ignores characters outside the alphabet.

          (get-delimited-base64
(open-string-input-port
"-----BEGIN EXAMPLE-----\n\
AAECAwQFBg==\n\
-----END EXAMPLE-----\n"))
⇒ "EXAMPLE"
⇒ #vu8(0 1 2 3 4 5 6)

— Constant: base64-alphabet

The alphabet used by the standard Base64 encoding. The alphabet is #\A#\Z, #\a#\z, #\0#\9, #\+, #\/.

— Constant: base64url-alphabet

The alphabet used by the base64url encoding. The alphabet is #\A#\Z, #\a#\z, #\0#\9, #\-, #\_.

Version history:

• (1 0) – Initial version.

Previous: text base64, Up: text

#### 2.7.2 Internet address parsing and formatting

The (weinholt text internet) library helps you correctly parse and format IPv4 and IPv6 addresses. This was a relatively trivial task when the Internet used the 32-bit IPv4 addresses. But when the newer 128-bit IPv6 addresses are represented as strings they can be compressed (meaning that sequences of zeroes may be omitted). An IPv6 address can actually be written in a great number of ways, and this has resulted in a recommended textual representation (RFC 5952).

The IPv6 code does not yet handle embedded IPv4 addresses.

— Procedure: ipv4->string bytevector

The IPv4 address in bytevector is converted to the canonical string representation.

— Procedure: string->ipv4 string

The textually represented IPv4 address in string is converted to its bytevector representation.

If the string does not represent an IPv4 address, #f is returned.

Note that this only handles the normal dotted-decimal notation. Some libraries, e.g. the standard C library, provide a function that parses addresses in octal, hex, and even handles some octets being missing. This library does none of that. Up to two leading zeroes may be used, though:

          (import (weinholt text internet))
(ipv4->string (string->ipv4 "192.000.002.000"))
⇒ "192.0.2.0"

— Procedure: ipv6->string bytevector

The IPv6 address in bytevector is converted to the string representation recommended by RFC 5952.

          (ipv6->string (string->ipv6 "2001:db8:0:0:0:0:0:1"))
⇒ "2001:db8::1"

— Procedure: string->ipv6 string

The textually represented IPv6 address in string is converted to its bytevector representation. The input may be in any valid format.

If the string does not represent an IPv6 address, #f is returned.

          (string->ipv6 "2001:db8:0:0:0:0:1")
⇒ #f

          (string->ipv6 "2001:db8::1")
⇒ #vu8(32 1 13 184 0 0 0 0 0 0 0 0 0 0 0 1)


Version history:

• (1 0) – Initial version.

Previous: text, Up: Library reference

### 2.8 Data types and utilities

Up: types

#### 2.8.1 Bytevector utilities

The (weinholt bytevectors) library contains utilities for working with R6RS bytevectors. For constructing and deconstructing bytevectors, see struct pack.

— Procedure: bytevector-append [bytevector ...]

Appends the given bytevectors.

— Procedure: bytevector-concatenate list

list is a list of bytevectors. The bytevectors are appended.

— Procedure: subbytevector bytevector start [end]

Analogous to substring. Returns a new bytevector containing the bytes of bytevector from index start to end (exclusive).

— Procedure: bytevector-u8-index bytevector byte [start end]

Searches bytevector for byte, from left to right. The optional arguments start and end give the range to search. By default the whole bytevector is searched. Returns #f is no match is found.

— Procedure: bytevector-u8-index-right bytevector byte [start end]

Analogous to bytevector-u8-index-right, except this procedure searches right-to-left.

— Procedure: bytevector->uint bytevector

bytevector is interpreted as an unsigned integer in big endian byte order and is converted to an integer. The empty bytevector is treated as zero.

— Procedure: uint->bytevector integer

integer is converted to an unsigned integer in big endian byte order. The returned bytevector has the minimum possible length. Zero is converted to the empty bytevector.

          (import (weinholt bytevectors))
(uint->bytevector 256)
⇒ #vu8(1 0)
(uint->bytevector 255)
⇒ #vu8(255)

— Procedure: bytevector=?/constant-time bytevector1 bytevector2

True if bytevector1 and bytevector2 are of equal length and have the same contents.

This is a drop-in replacement for bytevector=? that does not leak information about the outcome of the comparison by how much time the comparison takes to perform. It works by accumulating the differences between the bytevectors. This kind of operation is most often needed when comparing fixed-length message digests, so the length comparison is done in the obvious (fast) way.

Version history:

• (1 0) – Initial version.

Next: , Previous: Library reference, Up: Top

## 3 Demo programs

The programs directory contains small demonstration of the libraries. These scripts are implemented in the way recommended by R6RS

non-normative appendix D.

If you're packaging these libraries then I would recommend against installing the demos in the default program search path.

Next: , Up: Demo programs

### 3.1 checksig – verifies OpenPGP signature files

This program takes a detached ascii armored OpenPGP signature, a file to check against, and a GPG keyring. It then verifies the signature. As a curiosity it also prints OpenSSH-style random art for the key that made the signature.

Next: , Previous: checksig, Up: Demo programs

### 3.2 checksum – computes CRCs and message digests

Compute the hash or CRC of a file. Give it an algorithm and filenames and off it goes. It also demonstrates the superior slowness of the hashing libraries.

Next: , Previous: checksum, Up: Demo programs

### 3.3 fcdisasm – full-color disassembler

The Full-Color Disassembler, which disassembles machine code and colors the bytes in the hexdump. This makes it easy to see how many bytes all the different parts of an instruction uses.

Originally made for the x86 disassembler, so the hexdumps for other architectures might not be as nice. It now also supports HC12 and MIPS. It handles ELF files and assumes anything else is raw x86.

Next: , Previous: fcdisasm, Up: Demo programs

### 3.4 honingsburk – simple Secure Shell honey pot

This demonstrates the server part of the SSH library. It starts up a dummy SSH server that accepts logins with the username root and the password toor. The server does not create a real PTY and the client does not gain access to the computer running the server. It presents a command line where all commands return an error. It uses a few non-standard procedures from Ikarus.

Next: , Previous: honingsburk, Up: Demo programs

### 3.5 meircbot – the minimum-effort irc bot

The program file contains the configuration. It doesn't do anything other than joining channels and being rude in private messages. Shows how the (weinholt net irc) library can be used. It requires the (xitomatl AS-match) library.

It also uses demonstrates how to use FiSH, OTR and the simple TLS library.

Next: , Previous: meircbot, Up: Demo programs

### 3.6 secsh-client – manually operated Secure Shell client

Most SSH clients try to provide a nice user experience. This one is instead a command-line based manually operated client. After establishing the initial connection you can use a few simplistic commands to login, establish a session channel, read and write channel data. You can also enable debugging if you'd like to see a packet trace. This session log shows how to connect to a honingsburk running on TCP port 2222:

     Industria SSH demo client.

Connecting to localhost port 2222...
Running key exchange...
a6:4b:7e:05:38:03:01:29:07:0c:58:a4:fe:c1:d8:02
+---[ECDSA 521]---+
|*++o..           |
|ooo .            |
|Eo   . .         |
|o +   + .        |
| + +   oS.       |
|  o .  o  .      |
|   .  o  .       |
|     o ..        |
|      o.         |
+-----------------+

localhost ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1[...]
SSH session established.
Type help for a list of commands.

localhost=> u "root"
Your request to use ssh-userauth was accepted.
You may try these authentication methods: (password)
localhost=> p "toor"
You've succesfully authenticated.
localhost=> s
New session opened.
ID: 0 window size: 4096 maximum packet size: 32768
Send side parameters:
ID: 0 window size: 32768 maximum packet size: 32768
localhost=> t 0
localhost=> r
Linux darkstar 2.6.35.8 #1 Sat Oct 30 10:43:19 CEST 2010 i686

No mail.
localhost=> r

darkstar:~#
localhost=>


Next: , Previous: secsh-client, Up: Demo programs

### 3.7 sunzip – zip archive extractor

A simple program to extract (or list the contents of) zip archives. Can handle deflated files.

Next: , Previous: sunzip, Up: Demo programs

### 3.8 szip – zip archive creator

Creates zip files, but does not actually compress anything as of yet.

Next: , Previous: szip, Up: Demo programs

### 3.9 tarinfo – tarball information lister

Lists the contents of .tar and .tar.gz files. Sometimes these files contain more information than you think.

Previous: tarinfo, Up: Demo programs

### 3.10 tls-client – trivial HTTPS client

Demonstrates the simple TLS library. It connects to an HTTPS server, does a GET / request and displays the reply.

Previous: Demo programs, Up: Top