README.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>README</title>
  <style>
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  </style>
  <style>
  /*! normalize.css v2.1.3 | MIT License | git.io/normalize */

  /* ==========================================================================
     HTML5 display definitions
     ========================================================================== */

  /**
   * Correct `block` display not defined in IE 8/9.
   */

  article,
  aside,
  details,
  figcaption,
  figure,
  footer,
  header,
  hgroup,
  main,
  nav,
  section,
  summary {
      display: block;
  }

  /**
   * Correct `inline-block` display not defined in IE 8/9.
   */

  audio,
  canvas,
  video {
      display: inline-block;
  }

  /**
   * Prevent modern browsers from displaying `audio` without controls.
   * Remove excess height in iOS 5 devices.
   */

  audio:not([controls]) {
      display: none;
      height: 0;
  }

  /**
   * Address `[hidden]` styling not present in IE 8/9.
   * Hide the `template` element in IE, Safari, and Firefox < 22.
   */

  [hidden],
  template {
      display: none;
  }

  /* ==========================================================================
     Base
     ========================================================================== */

  /**
   * 1. Set default font family to sans-serif.
   * 2. Prevent iOS text size adjust after orientation change, without disabling
   *    user zoom.
   */

  html {
      font-family: sans-serif; /* 1 */
      -ms-text-size-adjust: 100%; /* 2 */
      -webkit-text-size-adjust: 100%; /* 2 */
  }

  /**
   * Remove default margin.
   */

  body {
      margin: 0;
  }

  /* ==========================================================================
     Links
     ========================================================================== */

  /**
   * Remove the gray background color from active links in IE 10.
   */

  a {
      background: transparent;
  }

  /**
   * Address `outline` inconsistency between Chrome and other browsers.
   */

  a:focus {
      outline: thin dotted;
  }

  /**
   * Improve readability when focused and also mouse hovered in all browsers.
   */

  a:active,
  a:hover {
      outline: 0;
  }

  /* ==========================================================================
     Typography
     ========================================================================== */

  /**
   * Address variable `h1` font-size and margin within `section` and `article`
   * contexts in Firefox 4+, Safari 5, and Chrome.
   */

  h1 {
      font-size: 2em;
      margin: 0.67em 0;
  }

  /**
   * Address styling not present in IE 8/9, Safari 5, and Chrome.
   */

  abbr[title] {
      border-bottom: 1px dotted;
  }

  /**
   * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
   */

  b,
  strong {
      font-weight: bold;
  }

  /**
   * Address styling not present in Safari 5 and Chrome.
   */

  dfn {
      font-style: italic;
  }

  /**
   * Address differences between Firefox and other browsers.
   */

  hr {
      -moz-box-sizing: content-box;
      box-sizing: content-box;
      height: 0;
  }

  /**
   * Address styling not present in IE 8/9.
   */

  mark {
      background: #ff0;
      color: #000;
  }

  /**
   * Correct font family set oddly in Safari 5 and Chrome.
   */

  code,
  kbd,
  pre,
  samp {
      font-family: monospace, serif;
      font-size: 1em;
  }

  /**
   * Improve readability of pre-formatted text in all browsers.
   */

  pre {
      white-space: pre-wrap;
  }

  /**
   * Set consistent quote types.
   */

  q {
      quotes: "\201C" "\201D" "\2018" "\2019";
  }

  /**
   * Address inconsistent and variable font size in all browsers.
   */

  small {
      font-size: 80%;
  }

  /**
   * Prevent `sub` and `sup` affecting `line-height` in all browsers.
   */

  sub,
  sup {
      font-size: 75%;
      line-height: 0;
      position: relative;
      vertical-align: baseline;
  }

  sup {
      top: -0.5em;
  }

  sub {
      bottom: -0.25em;
  }

  /* ==========================================================================
     Embedded content
     ========================================================================== */

  /**
   * Remove border when inside `a` element in IE 8/9.
   */

  img {
      border: 0;
  }

  /**
   * Correct overflow displayed oddly in IE 9.
   */

  svg:not(:root) {
      overflow: hidden;
  }

  /* ==========================================================================
     Figures
     ========================================================================== */

  /**
   * Address margin not present in IE 8/9 and Safari 5.
   */

  figure {
      margin: 0;
  }

  /* ==========================================================================
     Forms
     ========================================================================== */

  /**
   * Define consistent border, margin, and padding.
   */

  fieldset {
      border: 1px solid #c0c0c0;
      margin: 0 2px;
      padding: 0.35em 0.625em 0.75em;
  }

  /**
   * 1. Correct `color` not being inherited in IE 8/9.
   * 2. Remove padding so people aren't caught out if they zero out fieldsets.
   */

  legend {
      border: 0; /* 1 */
      padding: 0; /* 2 */
  }

  /**
   * 1. Correct font family not being inherited in all browsers.
   * 2. Correct font size not being inherited in all browsers.
   * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
   */

  button,
  input,
  select,
  textarea {
      font-family: inherit; /* 1 */
      font-size: 100%; /* 2 */
      margin: 0; /* 3 */
  }

  /**
   * Address Firefox 4+ setting `line-height` on `input` using `!important` in
   * the UA stylesheet.
   */

  button,
  input {
      line-height: normal;
  }

  /**
   * Address inconsistent `text-transform` inheritance for `button` and `select`.
   * All other form control elements do not inherit `text-transform` values.
   * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
   * Correct `select` style inheritance in Firefox 4+ and Opera.
   */

  button,
  select {
      text-transform: none;
  }

  /**
   * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
   *    and `video` controls.
   * 2. Correct inability to style clickable `input` types in iOS.
   * 3. Improve usability and consistency of cursor style between image-type
   *    `input` and others.
   */

  button,
  html input[type="button"], /* 1 */
  input[type="reset"],
  input[type="submit"] {
      -webkit-appearance: button; /* 2 */
      cursor: pointer; /* 3 */
  }

  /**
   * Re-set default cursor for disabled elements.
   */

  button[disabled],
  html input[disabled] {
      cursor: default;
  }

  /**
   * 1. Address box sizing set to `content-box` in IE 8/9/10.
   * 2. Remove excess padding in IE 8/9/10.
   */

  input[type="checkbox"],
  input[type="radio"] {
      box-sizing: border-box; /* 1 */
      padding: 0; /* 2 */
  }

  /**
   * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
   * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
   *    (include `-moz` to future-proof).
   */

  input[type="search"] {
      -webkit-appearance: textfield; /* 1 */
      -moz-box-sizing: content-box;
      -webkit-box-sizing: content-box; /* 2 */
      box-sizing: content-box;
  }

  /**
   * Remove inner padding and search cancel button in Safari 5 and Chrome
   * on OS X.
   */

  input[type="search"]::-webkit-search-cancel-button,
  input[type="search"]::-webkit-search-decoration {
      -webkit-appearance: none;
  }

  /**
   * Remove inner padding and border in Firefox 4+.
   */

  button::-moz-focus-inner,
  input::-moz-focus-inner {
      border: 0;
      padding: 0;
  }

  /**
   * 1. Remove default vertical scrollbar in IE 8/9.
   * 2. Improve readability and alignment in all browsers.
   */

  textarea {
      overflow: auto; /* 1 */
      vertical-align: top; /* 2 */
  }

  /* ==========================================================================
     Tables
     ========================================================================== */

  /**
   * Remove most spacing between table cells.
   */

  table {
      border-collapse: collapse;
      border-spacing: 0;
  }

  .go-top {
  position: fixed;
  bottom: 2em;
  right: 2em;
  text-decoration: none;
  background-color: #E0E0E0;
  font-size: 12px;
  padding: 1em;
  display: inline;
  }

  /* Github css */

  html,body{        margin: auto;
      padding-right: 1em;
      padding-left: 1em;
      max-width: 55em; color:black;}*:not('#mkdbuttons'){margin:0;padding:0}body{font:13.34px helvetica,arial,freesans,clean,sans-serif;-webkit-font-smoothing:subpixel-antialiased;line-height:1.4;padding:3px;background:#fff;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}p{margin:1em 0}a{color:#4183c4;text-decoration:none}body{background-color:#fff;padding:30px;margin:15px;font-size:14px;line-height:1.6}body>*:first-child{margin-top:0!important}body>*:last-child{margin-bottom:0!important}@media screen{body{box-shadow:0 0 0 1px #cacaca,0 0 0 4px #eee}}h1,h2,h3,h4,h5,h6{margin:20px 0 10px;padding:0;font-weight:bold;-webkit-font-smoothing:subpixel-antialiased;cursor:text}h1{font-size:28px;color:#000}h2{font-size:24px;border-bottom:1px solid #ccc;color:#000}h3{font-size:18px;color:#333}h4{font-size:16px;color:#333}h5{font-size:14px;color:#333}h6{color:#777;font-size:14px}p,blockquote,table,pre{margin:15px 0}ul{padding-left:30px}ol{padding-left:30px}ol li ul:first-of-type{margin-top:0}hr{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;border:0 none;color:#ccc;height:4px;padding:0}body>h2:first-child{margin-top:0;padding-top:0}body>h1:first-child{margin-top:0;padding-top:0}body>h1:first-child+h2{margin-top:0;padding-top:0}body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child{margin-top:0;padding-top:0}a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6{margin-top:0;padding-top:0}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p,ul li>:first-child,ol li>:first-child{margin-top:0}dl{padding:0}dl dt{font-size:14px;font-weight:bold;font-style:italic;padding:0;margin:15px 0 5px}dl dt:first-child{padding:0}dl dt>:first-child{margin-top:0}dl dt>:last-child{margin-bottom:0}dl dd{margin:0 0 15px;padding:0 15px}dl dd>:first-child{margin-top:0}dl dd>:last-child{margin-bottom:0}blockquote{border-left:4px solid #DDD;padding:0 15px;color:#777}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}table{border-collapse:collapse;border-spacing:0;font-size:100%;font:inherit}table th{font-weight:bold;border:1px solid #ccc;padding:6px 13px}table td{border:1px solid #ccc;padding:6px 13px}table tr{border-top:1px solid #ccc;background-color:#fff}table tr:nth-child(2n){background-color:#f8f8f8}img{max-width:100%}code,tt{margin:0 2px;padding:0 5px;white-space:nowrap;border:1px solid #eaeaea;background-color:#f8f8f8;border-radius:3px;font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;color:#333}pre>code{margin:0;padding:0;white-space:pre;border:0;background:transparent}.highlight pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre code,pre tt{background-color:transparent;border:0}.poetry pre{font-family:Georgia,Garamond,serif!important;font-style:italic;font-size:110%!important;line-height:1.6em;display:block;margin-left:1em}.poetry pre code{font-family:Georgia,Garamond,serif!important;word-break:break-all;word-break:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto;white-space:pre-wrap}sup,sub,a.footnote{font-size:1.4ex;height:0;line-height:1;vertical-align:super;position:relative}sub{vertical-align:sub;top:-1px}@media print{body{background:#fff}img,pre,blockquote,table,figure{page-break-inside:avoid}body{background:#fff;border:0}code{background-color:#fff;color:#333!important;padding:0 .2em;border:1px solid #dedede}pre{background:#fff}pre code{background-color:white!important;overflow:visible}}@media screen{body.inverted{color:#eee!important;border-color:#555;box-shadow:none}.inverted body,.inverted hr .inverted p,.inverted td,.inverted li,.inverted h1,.inverted h2,.inverted h3,.inverted h4,.inverted h5,.inverted h6,.inverted th,.inverted .math,.inverted caption,.inverted dd,.inverted dt,.inverted blockquote{color:#eee!important;border-color:#555;box-shadow:none}.inverted td,.inverted th{background:#333}.inverted h2{border-color:#555}.inverted hr{border-color:#777;border-width:1px!important}::selection{background:rgba(157,193,200,0.5)}h1::selection{background-color:rgba(45,156,208,0.3)}h2::selection{background-color:rgba(90,182,224,0.3)}h3::selection,h4::selection,h5::selection,h6::selection,li::selection,ol::selection{background-color:rgba(133,201,232,0.3)}code::selection{background-color:rgba(0,0,0,0.7);color:#eee}code span::selection{background-color:rgba(0,0,0,0.7)!important;color:#eee!important}a::selection{background-color:rgba(255,230,102,0.2)}.inverted a::selection{background-color:rgba(255,230,102,0.6)}td::selection,th::selection,caption::selection{background-color:rgba(180,237,95,0.5)}.inverted{background:#0b2531;background:#252a2a}.inverted body{background:#252a2a}.inverted a{color:#acd1d5}}.highlight .c{color:#998;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .k,.highlight .o{font-weight:bold}.highlight .cm{color:#998;font-style:italic}.highlight .cp{color:#999;font-weight:bold}.highlight .c1{color:#998;font-style:italic}.highlight .cs{color:#999;font-weight:bold;font-style:italic}.highlight .gd{color:#000;background-color:#fdd}.highlight .gd .x{color:#000;background-color:#faa}.highlight .ge{font-style:italic}.highlight .gr{color:#a00}.highlight .gh{color:#999}.highlight .gi{color:#000;background-color:#dfd}.highlight .gi .x{color:#000;background-color:#afa}.highlight .go{color:#888}.highlight .gp{color:#555}.highlight .gs{font-weight:bold}.highlight .gu{color:#800080;font-weight:bold}.highlight .gt{color:#a00}.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{font-weight:bold}.highlight .kt{color:#458;font-weight:bold}.highlight .m{color:#099}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .nb{color:#0086b3}.highlight .nc{color:#458;font-weight:bold}.highlight .no{color:#008080}.highlight .ni{color:#800080}.highlight .ne,.highlight .nf{color:#900;font-weight:bold}.highlight .nn{color:#555}.highlight .nt{color:#000080}.highlight .nv{color:#008080}.highlight .ow{font-weight:bold}.highlight .w{color:#bbb}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#099}.highlight .sb,.highlight .sc,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999}.highlight .vc,.highlight .vg,.highlight .vi{color:#008080}.highlight .il{color:#099}.highlight .gc{color:#999;background-color:#eaf2f5}.type-csharp .highlight .k,.type-csharp .highlight .kt{color:#00F}.type-csharp .highlight .nf{color:#000;font-weight:normal}.type-csharp .highlight .nc{color:#2b91af}.type-csharp .highlight .nn{color:#000}.type-csharp .highlight .s,.type-csharp .highlight .sc{color:#a31515}
  </style>
</head>
<body>
<p><img src="https://github.com/simplito/ecies-erl/actions/workflows/erlang.yml/badge.svg" alt="Build and Test" /> <a href="https://hex.pm/packages/ecies"><img src="https://img.shields.io/hexpm/v/ecies.svg" alt="Hex" /></a></p>
<h1 id="customizable-erlang-native-ecies-public-key-cryptography-library">Customizable Erlang native ECIES public-key cryptography library</h1>
<p>An Erlang native library implementing the ECIES (Elliptic Curve Integrated Encryption Scheme) public-key cryptography.<br />
It allows for configurable components such as DH key agreement, key derivation, data encryption, MAC algorithms and more.</p>
<p>Examples tailored to ECIES variants implemented in Electrum, Geth, and Bitcore are also provided.</p>
<h2 id="motivation">Motivation</h2>
<p>The Erlang OTP team decided to deprecate several <code>crypto</code> module functions in OTP 27 (See <a href="https://www.erlang.org/doc/deprecations.html#functions-deprecated-in-otp-27">functions deprecated in OTP 27</a>)<br />
Notably, no alternatives were provided for two of them <code>crypto:public_encrypt/4</code>, <code>crypto:private_decrypt/4</code>.<br />
It is worth mentioning that the above mentioned functions are RSA specific and cannot be used with Elliptic Curve cryptography anyway.</p>
<p>Some information about potential background of these deprecations can be found <a href="https://erlangforums.com/t/security-working-group-minutes/3451/6">here</a>.</p>
<p>In our projects we mainly use Elliptic Curve cryptography and we decided to share this small library for ECIES with the Erlang developers community.<br />
We will be happy if you find it useful and use in your project. If you find any ideas for improvements or notice any missing functionality, please open an issue here; even better propose a Pull Request.</p>
<h2 id="usage">Usage</h2>
<h3 id="basic">Basic</h3>
<p>The simplest variant without additionals params:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode erlang"><code class="sourceCode erlang"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>  <span class="co">% Bob generates keys</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a>  <span class="fu">{</span><span class="va">BobPublicKey</span><span class="fu">,</span> <span class="va">BobPrivateKey</span><span class="fu">}</span> <span class="op">=</span> <span class="fu">ecies:generate_key(),</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a>  <span class="co">% Alice knowing Bob&#39;s public key encrypts a message for him</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a>  <span class="va">Data</span> <span class="op">=</span> <span class="fu">ecies:public_encrypt(</span><span class="va">BobPublicKey</span><span class="fu">,</span> <span class="op">&lt;&lt;</span><span class="st">&quot;top secret message&quot;</span><span class="op">&gt;&gt;</span><span class="fu">),</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a>  <span class="co">% Bob is able to decrypt the message using his private key</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a>  <span class="op">&lt;&lt;</span><span class="st">&quot;top secret message&quot;</span><span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="fu">ecies:private_decrypt(</span><span class="va">BobPrivateKey</span><span class="fu">,</span> <span class="va">Data</span><span class="fu">).</span></span></code></pre></div>
<p>In that case the default params are used (as returned by <code>ecies:default_params/0</code>):</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode erlang"><code class="sourceCode erlang"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a>  <span class="fu">#{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>    <span class="ch">curve</span>    <span class="op">=&gt;</span> <span class="ch">secp256k1</span><span class="fu">,</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a>    <span class="ch">cipher</span>   <span class="op">=&gt;</span> <span class="ch">aes_256_cbc</span><span class="fu">,</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a>    <span class="ch">kdf</span>      <span class="op">=&gt;</span> <span class="fu">{</span><span class="ch">kdf</span><span class="fu">,</span> <span class="ch">sha256</span><span class="fu">},</span>      <span class="co">% ANSI-X9.63 key derivation</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a>    <span class="ch">mac</span>      <span class="op">=&gt;</span> <span class="fu">{</span><span class="ch">hmac</span><span class="fu">,</span> <span class="ch">sha256</span><span class="fu">,</span> <span class="dv">256</span><span class="fu">}</span> <span class="co">% HMAC SHA256 with 256 bits (32 bytes) output</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a>  <span class="fu">}.</span></span></code></pre></div>
<h3 id="customisation">Customisation</h3>
<p>Specifying additional argument <code>Params</code> to the <code>generate_key</code>, <code>public_encrypt</code> and <code>privated_decrypt</code> function you can customize algorithms used in all steps of encryption / decryption.</p>
<p>Example:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode erlang"><code class="sourceCode erlang"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a>  <span class="co">% Alice and Bob agrees on the following params</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a>  <span class="va">Params</span> <span class="op">=</span> <span class="fu">#{</span> <span class="ch">curve</span> <span class="op">=&gt;</span> <span class="ch">x25519</span><span class="fu">,</span> <span class="ch">kdf</span> <span class="op">=&gt;</span> <span class="fu">{</span><span class="ch">hkdf</span><span class="fu">,</span> <span class="ch">sha256</span><span class="fu">},</span> <span class="ch">cipher</span> <span class="op">=&gt;</span> <span class="ch">aes_256_ctr</span><span class="fu">,</span> <span class="ch">mac</span> <span class="op">=&gt;</span> <span class="fu">{</span><span class="ch">hmac</span><span class="fu">,</span> <span class="ch">sha256</span><span class="fu">,</span> <span class="dv">96</span><span class="fu">}</span> <span class="fu">},</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a>  <span class="co">% Bob generates keys</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a>  <span class="fu">{</span><span class="va">BobPublicKey</span><span class="fu">,</span> <span class="va">BobPrivateKey</span><span class="fu">}</span> <span class="op">=</span> <span class="fu">ecies:generate_key(</span><span class="va">Params</span><span class="fu">),</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a>  <span class="co">% Alice knowing Bob&#39;s public key encrypts a message for him</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a>  <span class="va">Data</span> <span class="op">=</span> <span class="fu">ecies:public_encrypt(</span><span class="va">BobPublicKey</span><span class="fu">,</span> <span class="op">&lt;&lt;</span><span class="st">&quot;top secret message&quot;</span><span class="op">&gt;&gt;</span><span class="fu">,</span> <span class="va">Params</span><span class="fu">),</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a>  <span class="co">% Bob is able to decrypt the message using his private key</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a>  <span class="op">&lt;&lt;</span><span class="st">&quot;top secret message&quot;</span><span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="fu">ecies:private_decrypt(</span><span class="va">BobPrivateKey</span><span class="fu">,</span> <span class="va">Data</span><span class="fu">,</span> <span class="va">Params</span><span class="fu">).</span></span></code></pre></div>
<p>The list of all supported elliptic curves (<code>curve</code> param), ciphers (<code>cipher</code> param) and hash functions used by KDF and MAC algorithms can be obtained using <code>ecies:supports/1</code> function:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode erlang"><code class="sourceCode erlang"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="op">-</span><span class="ch">spec</span> <span class="fu">supports(</span><span class="ch">hashs</span><span class="fu">)</span>  <span class="op">-&gt;</span> <span class="fu">[digest_type()];</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a>              <span class="fu">(</span><span class="ch">curves</span><span class="fu">)</span> <span class="op">-&gt;</span> <span class="fu">[named_curve()];</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a>              <span class="fu">(</span><span class="ch">ciphers</span><span class="fu">)</span> <span class="op">-&gt;</span> <span class="fu">[cipher()];</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a>              <span class="fu">(</span><span class="ch">cmac_ciphers</span><span class="fu">)</span> <span class="op">-&gt;</span> <span class="fu">[cmac_cipher()];</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a>              <span class="fu">(</span><span class="ch">aead_ciphers</span><span class="fu">)</span> <span class="op">-&gt;</span> <span class="fu">[aead_cipher()].</span></span></code></pre></div>
<p>NOTE: For Edwards Curves 25519 and 448 do use <code>x25519</code> and <code>x448</code>.</p>
<p>For key derivation (<code>kdf</code> param) you can use:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode erlang"><code class="sourceCode erlang"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="op">-</span><span class="ch">type</span> <span class="fu">kdf_type()</span> <span class="fu">::</span> <span class="fu">{</span><span class="ch">hkdf</span><span class="fu">,</span> <span class="fu">digest_type()}</span> <span class="fu">|</span> <span class="co">% HMAC-based Extract-and-Expand Key Derivation Function (HKDF)</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a>                    <span class="fu">{</span><span class="ch">kdf</span><span class="fu">,</span> <span class="fu">digest_type()}</span>  <span class="fu">|</span> <span class="co">% ANSI-X9.63 KDF</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a>                    <span class="fu">{</span><span class="ch">concat_kdf</span><span class="fu">,</span> <span class="fu">digest_type()}</span>  <span class="fu">|</span> <span class="co">% NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a>                    <span class="fu">kdf_fun().</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="co">% Custom KDF function</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="op">-</span><span class="ch">type</span> <span class="fu">kdf_fun()</span>  <span class="fu">::</span> <span class="kw">fun</span><span class="fu">((</span><span class="va">SharedKey</span> <span class="fu">::</span> <span class="fu">binary(),</span> <span class="va">Info</span> <span class="fu">::</span> <span class="fu">binary(),</span> <span class="va">Length</span> <span class="fu">::</span> <span class="fu">pos_integer())</span> <span class="op">-&gt;</span> <span class="va">Result</span> <span class="fu">::</span> <span class="fu">binary()).</span></span></code></pre></div>
<p>For message authentication (<code>mac</code> param):</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode erlang"><code class="sourceCode erlang"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="op">-</span><span class="ch">type</span> <span class="fu">mac_type()</span>    <span class="fu">::</span> <span class="fu">{</span><span class="ch">hmac</span><span class="fu">,</span> <span class="fu">digest_type(),</span> <span class="fu">mac_bits()}</span> <span class="fu">|</span> <span class="co">% HMAC for given digest function with specified output bits</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a>                       <span class="fu">{</span><span class="ch">cmac</span><span class="fu">,</span> <span class="fu">cmac_cipher(),</span> <span class="fu">mac_bits()}</span> <span class="fu">|</span> <span class="co">% CMAC with AES-*-CBC cipher and given output bits</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a>                       <span class="fu">{</span><span class="ch">aead</span><span class="fu">,</span> <span class="fu">mac_bits()}.</span> <span class="co">% Special case when AES CCM/GCM ciphers are used to just specify tag output bits </span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="op">-</span><span class="ch">type</span> <span class="fu">mac_bits()</span>    <span class="fu">::</span> <span class="fu">pos_integer()</span> <span class="fu">|</span> <span class="ch">default</span><span class="fu">.</span> <span class="co">% default atom means output size equal to given mac key length</span></span></code></pre></div>
<p>Additionally we provide default params used in bitcore<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>, geth<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>, electrum<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>.</p>
<p>Example usage:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode erlang"><code class="sourceCode erlang"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a>  <span class="va">Params</span> <span class="op">=</span> <span class="fu">ecies_electrum:default_params(),</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a>  <span class="va">PrivateKey</span> <span class="op">=</span> <span class="fu">binary:decode_hex(</span><span class="op">&lt;&lt;</span><span class="st">&quot;ee3231b5deea48b619814d72a6e1aa04a9f521df281afad5ada89f5393941b1c&quot;</span><span class="op">&gt;&gt;</span><span class="fu">),</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a>  <span class="va">MessageBase64</span> <span class="op">=</span> <span class="op">&lt;&lt;</span><span class="st">&quot;QklFMQJdmY+9Ys1WjqANreLwXaau62N01r9lebJ9Rp7Az+XRMdNAVgg3J8EEVhni5gn2v+WOD59uDMDp0zY/xPT3IElReQo6XUCSMmgRgRtYl+TUEw==&quot;</span><span class="op">&gt;&gt;</span><span class="fu">,</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a>  <span class="op">&lt;&lt;</span><span class="st">&quot;hello world&quot;</span><span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="fu">ecies:private_decrypt(</span><span class="va">PrivateKey</span><span class="fu">,</span> <span class="va">MessageBase64</span><span class="fu">,</span> <span class="va">Params</span><span class="fu">).</span></span></code></pre></div>
<p>NOTE: Unfortunately Electrum uses full compressed point from Diffie-Hellman step of calculating shared key instead of usual x coordinate, and erlang’s <code>crypto:compute_key</code> is not enough to calculate this. For using electrum compatible params you need to add <code>libsecp256k1</code> to your dependencies, otherwise <code>error(unsupported)</code> will be thrown.</p>
<p>More advanced usage cases will be described later.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p><a href="https://www.researchgate.net/publication/251958691_A_comparison_of_the_standardized_versions_of_ECIES">A comparison of the standardized versions of ECIES.</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>https://github.com/bitpay/bitcore-ecies<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>https://github.com/ethereum/go-ethereum/blob/master/crypto/ecies/ecies.go<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</body>
</html>