5898 lines
294 KiB
HTML
5898 lines
294 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="en" class="RFC">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta content="Common,Latin" name="scripts">
|
||
<meta content="initial-scale=1.0" name="viewport">
|
||
<title>RFC 9807: The OPAQUE Augmented Password-Authenticated Key Exchange (aPAKE) Protocol</title>
|
||
<meta content="Daniel Bourdrez" name="author">
|
||
<meta content="Hugo Krawczyk" name="author">
|
||
<meta content="Kevin Lewi" name="author">
|
||
<meta content="Christopher A. Wood" name="author">
|
||
<meta content="
|
||
This document describes the OPAQUE protocol, an Augmented (or Asymmetric)
|
||
Password-Authenticated Key Exchange (aPAKE) protocol that supports mutual
|
||
authentication in a client-server setting without reliance on PKI and
|
||
with security against pre-computation attacks upon server compromise.
|
||
In addition, the protocol provides forward secrecy and the ability to
|
||
hide the password from the server, even during password registration.
|
||
This document specifies the core OPAQUE protocol and one instantiation
|
||
based on 3DH. This document is a product of the Crypto Forum Research
|
||
Group (CFRG) in the IRTF.
|
||
" name="description">
|
||
<meta content="xml2rfc 3.30.0" name="generator">
|
||
<meta content="9807" name="rfc.number">
|
||
<!-- Generator version information:
|
||
xml2rfc 3.30.0
|
||
Python 3.9.15
|
||
ConfigArgParse 1.5.3
|
||
google-i18n-address 3.0.0
|
||
intervaltree 3.1.0
|
||
Jinja2 3.1.2
|
||
lxml 5.3.0
|
||
platformdirs 3.8.0
|
||
pycountry 22.3.5
|
||
PyYAML 6.0
|
||
requests 2.28.0
|
||
setuptools 44.1.1
|
||
six 1.16.0
|
||
wcwidth 0.2.5
|
||
weasyprint 65.0
|
||
-->
|
||
<link href="rfc9807.xml" rel="alternate" type="application/rfc+xml">
|
||
<link href="#copyright" rel="license">
|
||
<style type="text/css">/*
|
||
|
||
NOTE: Changes at the bottom of this file overrides some earlier settings.
|
||
|
||
Once the style has stabilized and has been adopted as an official RFC style,
|
||
this can be consolidated so that style settings occur only in one place, but
|
||
for now the contents of this file consists first of the initial CSS work as
|
||
provided to the RFC Formatter (xml2rfc) work, followed by itemized and
|
||
commented changes found necessary during the development of the v3
|
||
formatters.
|
||
|
||
*/
|
||
|
||
/* fonts */
|
||
@import url('https://fonts.googleapis.com/css?family=Noto+Sans'); /* Sans-serif */
|
||
@import url('https://fonts.googleapis.com/css?family=Noto+Serif'); /* Serif (print) */
|
||
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono'); /* Monospace */
|
||
|
||
:root {
|
||
--font-sans: 'Noto Sans', Arial, Helvetica, sans-serif;
|
||
--font-serif: 'Noto Serif', 'Times', 'Times New Roman', serif;
|
||
--font-mono: 'Roboto Mono', Courier, 'Courier New', monospace;
|
||
}
|
||
|
||
@viewport {
|
||
zoom: 1.0;
|
||
}
|
||
@-ms-viewport {
|
||
width: extend-to-zoom;
|
||
zoom: 1.0;
|
||
}
|
||
/* general and mobile first */
|
||
html {
|
||
}
|
||
body {
|
||
max-width: 90%;
|
||
margin: 1.5em auto;
|
||
color: #222;
|
||
background-color: #fff;
|
||
font-size: 14px;
|
||
font-family: var(--font-sans);
|
||
line-height: 1.6;
|
||
scroll-behavior: smooth;
|
||
overflow-wrap: break-word;
|
||
}
|
||
.ears {
|
||
display: none;
|
||
}
|
||
|
||
/* headings */
|
||
#title, h1, h2, h3, h4, h5, h6 {
|
||
margin: 1em 0 0.5em;
|
||
font-weight: bold;
|
||
line-height: 1.3;
|
||
}
|
||
#title {
|
||
clear: both;
|
||
border-bottom: 1px solid #ddd;
|
||
margin: 0 0 0.5em 0;
|
||
padding: 1em 0 0.5em;
|
||
}
|
||
.author {
|
||
padding-bottom: 4px;
|
||
}
|
||
h1 {
|
||
font-size: 26px;
|
||
margin: 1em 0;
|
||
}
|
||
h2 {
|
||
font-size: 22px;
|
||
margin-top: -20px; /* provide offset for in-page anchors */
|
||
padding-top: 33px;
|
||
}
|
||
h3 {
|
||
font-size: 18px;
|
||
margin-top: -36px; /* provide offset for in-page anchors */
|
||
padding-top: 42px;
|
||
}
|
||
h4 {
|
||
font-size: 16px;
|
||
margin-top: -36px; /* provide offset for in-page anchors */
|
||
padding-top: 42px;
|
||
}
|
||
h5, h6 {
|
||
font-size: 14px;
|
||
}
|
||
#n-copyright-notice {
|
||
border-bottom: 1px solid #ddd;
|
||
padding-bottom: 1em;
|
||
margin-bottom: 1em;
|
||
}
|
||
/* general structure */
|
||
p {
|
||
padding: 0;
|
||
margin: 0 0 1em 0;
|
||
text-align: left;
|
||
}
|
||
div, span {
|
||
position: relative;
|
||
}
|
||
div {
|
||
margin: 0;
|
||
}
|
||
.alignRight.art-text {
|
||
background-color: #f9f9f9;
|
||
border: 1px solid #eee;
|
||
border-radius: 3px;
|
||
padding: 1em 1em 0;
|
||
margin-bottom: 1.5em;
|
||
}
|
||
.alignRight.art-text pre {
|
||
padding: 0;
|
||
}
|
||
.alignRight {
|
||
margin: 1em 0;
|
||
}
|
||
.alignRight > *:first-child {
|
||
border: none;
|
||
margin: 0;
|
||
float: right;
|
||
clear: both;
|
||
}
|
||
.alignRight > *:nth-child(2) {
|
||
clear: both;
|
||
display: block;
|
||
border: none;
|
||
}
|
||
svg {
|
||
display: block;
|
||
}
|
||
@media print {
|
||
svg {
|
||
max-height: 850px;
|
||
max-width: 660px;
|
||
}
|
||
}
|
||
svg[font-family~="serif" i], svg [font-family~="serif" i] {
|
||
font-family: var(--font-serif);
|
||
}
|
||
svg[font-family~="sans-serif" i], svg [font-family~="sans-serif" i] {
|
||
font-family: var(--font-sans);
|
||
}
|
||
svg[font-family~="monospace" i], svg [font-family~="monospace" i] {
|
||
font-family: var(--font-mono);
|
||
}
|
||
.alignCenter.art-text {
|
||
background-color: #f9f9f9;
|
||
border: 1px solid #eee;
|
||
border-radius: 3px;
|
||
padding: 1em 1em 0;
|
||
margin-bottom: 1.5em;
|
||
}
|
||
.alignCenter.art-text pre {
|
||
padding: 0;
|
||
}
|
||
.alignCenter {
|
||
margin: 1em 0;
|
||
}
|
||
.alignCenter > *:first-child {
|
||
display: table;
|
||
border: none;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
/* lists */
|
||
ol, ul {
|
||
padding: 0;
|
||
margin: 0 0 1em 2em;
|
||
}
|
||
ol ol, ul ul, ol ul, ul ol {
|
||
margin-left: 1em;
|
||
}
|
||
li {
|
||
margin: 0 0 0.25em 0;
|
||
}
|
||
.ulCompact li {
|
||
margin: 0;
|
||
}
|
||
ul.empty, .ulEmpty {
|
||
list-style-type: none;
|
||
}
|
||
ul.empty li, .ulEmpty li {
|
||
margin-top: 0.5em;
|
||
}
|
||
ul.ulBare, li.ulBare {
|
||
margin-left: 0em !important;
|
||
}
|
||
ul.compact, .ulCompact,
|
||
ol.compact, .olCompact {
|
||
line-height: 100%;
|
||
margin: 0 0 0 2em;
|
||
}
|
||
|
||
/* definition lists */
|
||
dl {
|
||
}
|
||
dl > dt {
|
||
float: left;
|
||
margin-right: 1em;
|
||
}
|
||
/*
|
||
dl.nohang > dt {
|
||
float: none;
|
||
}
|
||
*/
|
||
dl > dd {
|
||
margin-bottom: .8em;
|
||
min-height: 1.3em;
|
||
}
|
||
dl.compact > dd, .dlCompact > dd {
|
||
margin-bottom: 0em;
|
||
}
|
||
dl > dd > dl {
|
||
margin-top: 0.5em;
|
||
margin-bottom: 0em;
|
||
}
|
||
|
||
/* links */
|
||
a {
|
||
text-decoration: none;
|
||
}
|
||
a[href] {
|
||
color: #22e; /* Arlen: WCAG 2019 */
|
||
}
|
||
a[href]:hover {
|
||
background-color: #f2f2f2;
|
||
}
|
||
figcaption a[href],
|
||
a[href].selfRef {
|
||
color: #222;
|
||
}
|
||
/* XXX probably not this:
|
||
a.selfRef:hover {
|
||
background-color: transparent;
|
||
cursor: default;
|
||
} */
|
||
|
||
/* Figures */
|
||
tt, code, pre {
|
||
background-color: #f9f9f9;
|
||
font-family: var(--font-mono);
|
||
}
|
||
pre {
|
||
border: 1px solid #eee;
|
||
margin: 0;
|
||
padding: 1em;
|
||
}
|
||
img {
|
||
max-width: 100%;
|
||
}
|
||
figure {
|
||
margin: 0;
|
||
}
|
||
figure blockquote {
|
||
margin: 0.8em 0.4em 0.4em;
|
||
}
|
||
figcaption {
|
||
font-style: italic;
|
||
margin: 0 0 1em 0;
|
||
}
|
||
@media screen {
|
||
pre {
|
||
overflow-x: auto;
|
||
max-width: 100%;
|
||
max-width: calc(100% - 22px);
|
||
}
|
||
}
|
||
|
||
/* aside, blockquote */
|
||
aside, blockquote {
|
||
margin-left: 0;
|
||
padding: 1.2em 2em;
|
||
}
|
||
blockquote {
|
||
background-color: #f9f9f9;
|
||
color: #111; /* Arlen: WCAG 2019 */
|
||
border: 1px solid #ddd;
|
||
border-radius: 3px;
|
||
margin: 1em 0;
|
||
}
|
||
blockquote > *:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
cite {
|
||
display: block;
|
||
text-align: right;
|
||
font-style: italic;
|
||
}
|
||
.xref {
|
||
overflow-wrap: normal;
|
||
}
|
||
|
||
/* tables */
|
||
table {
|
||
width: 100%;
|
||
margin: 0 0 1em;
|
||
border-collapse: collapse;
|
||
border: 1px solid #eee;
|
||
}
|
||
th, td {
|
||
text-align: left;
|
||
vertical-align: top;
|
||
padding: 0.5em 0.75em;
|
||
}
|
||
th {
|
||
text-align: left;
|
||
background-color: #e9e9e9;
|
||
}
|
||
tr:nth-child(2n+1) > td {
|
||
background-color: #f5f5f5;
|
||
}
|
||
table caption {
|
||
font-style: italic;
|
||
margin: 0;
|
||
padding: 0;
|
||
text-align: left;
|
||
}
|
||
table p {
|
||
/* XXX to avoid bottom margin on table row signifiers. If paragraphs should
|
||
be allowed within tables more generally, it would be far better to select on a class. */
|
||
margin: 0;
|
||
}
|
||
|
||
/* pilcrow */
|
||
a.pilcrow {
|
||
color: #666; /* Arlen: AHDJ 2019 */
|
||
text-decoration: none;
|
||
visibility: hidden;
|
||
user-select: none;
|
||
-ms-user-select: none;
|
||
-o-user-select:none;
|
||
-moz-user-select: none;
|
||
-khtml-user-select: none;
|
||
-webkit-user-select: none;
|
||
-webkit-touch-callout: none;
|
||
}
|
||
@media screen {
|
||
aside:hover > a.pilcrow,
|
||
p:hover > a.pilcrow,
|
||
blockquote:hover > a.pilcrow,
|
||
div:hover > a.pilcrow,
|
||
li:hover > a.pilcrow,
|
||
pre:hover > a.pilcrow {
|
||
visibility: visible;
|
||
}
|
||
a.pilcrow:hover {
|
||
background-color: transparent;
|
||
}
|
||
}
|
||
|
||
/* misc */
|
||
hr {
|
||
border: 0;
|
||
border-top: 1px solid #eee;
|
||
}
|
||
.bcp14 {
|
||
font-variant: small-caps;
|
||
}
|
||
|
||
.role {
|
||
font-variant: all-small-caps;
|
||
}
|
||
|
||
/* info block */
|
||
#identifiers {
|
||
margin: 0;
|
||
font-size: 0.9em;
|
||
}
|
||
#identifiers dt {
|
||
width: 3em;
|
||
clear: left;
|
||
}
|
||
#identifiers dd {
|
||
float: left;
|
||
margin-bottom: 0;
|
||
}
|
||
/* Fix PDF info block run off issue */
|
||
@media print {
|
||
#identifiers dd {
|
||
max-width: 100%;
|
||
}
|
||
}
|
||
#identifiers .authors .author {
|
||
display: inline-block;
|
||
margin-right: 1.5em;
|
||
}
|
||
#identifiers .authors .org {
|
||
font-style: italic;
|
||
}
|
||
|
||
/* The prepared/rendered info at the very bottom of the page */
|
||
.docInfo {
|
||
color: #666; /* Arlen: WCAG 2019 */
|
||
font-size: 0.9em;
|
||
font-style: italic;
|
||
margin-top: 2em;
|
||
}
|
||
.docInfo .prepared {
|
||
float: left;
|
||
}
|
||
.docInfo .prepared {
|
||
float: right;
|
||
}
|
||
|
||
/* table of contents */
|
||
#toc {
|
||
padding: 0.75em 0 2em 0;
|
||
margin-bottom: 1em;
|
||
}
|
||
nav.toc ul {
|
||
margin: 0 0.5em 0 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
nav.toc li {
|
||
line-height: 1.3em;
|
||
margin: 0.75em 0;
|
||
padding-left: 1.2em;
|
||
text-indent: -1.2em;
|
||
}
|
||
/* references */
|
||
.references dt {
|
||
text-align: right;
|
||
font-weight: bold;
|
||
min-width: 7em;
|
||
}
|
||
.references dd {
|
||
margin-left: 8em;
|
||
overflow: auto;
|
||
}
|
||
|
||
.refInstance {
|
||
margin-bottom: 1.25em;
|
||
}
|
||
|
||
.refSubseries {
|
||
margin-bottom: 1.25em;
|
||
}
|
||
|
||
.references .ascii {
|
||
margin-bottom: 0.25em;
|
||
}
|
||
|
||
/* index */
|
||
.index ul {
|
||
margin: 0 0 0 1em;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
.index ul ul {
|
||
margin: 0;
|
||
}
|
||
.index li {
|
||
margin: 0;
|
||
text-indent: -2em;
|
||
padding-left: 2em;
|
||
padding-bottom: 5px;
|
||
}
|
||
.indexIndex {
|
||
margin: 0.5em 0 1em;
|
||
}
|
||
.index a {
|
||
font-weight: 700;
|
||
}
|
||
/* make the index two-column on all but the smallest screens */
|
||
@media (min-width: 600px) {
|
||
.index ul {
|
||
-moz-column-count: 2;
|
||
-moz-column-gap: 20px;
|
||
}
|
||
.index ul ul {
|
||
-moz-column-count: 1;
|
||
-moz-column-gap: 0;
|
||
}
|
||
}
|
||
|
||
/* authors */
|
||
address.vcard {
|
||
font-style: normal;
|
||
margin: 1em 0;
|
||
}
|
||
|
||
address.vcard .nameRole {
|
||
font-weight: 700;
|
||
margin-left: 0;
|
||
}
|
||
address.vcard .label {
|
||
font-family: var(--font-sans);
|
||
margin: 0.5em 0;
|
||
}
|
||
address.vcard .type {
|
||
display: none;
|
||
}
|
||
.alternative-contact {
|
||
margin: 1.5em 0 1em;
|
||
}
|
||
hr.addr {
|
||
border-top: 1px dashed;
|
||
margin: 0;
|
||
color: #ddd;
|
||
max-width: calc(100% - 16px);
|
||
}
|
||
|
||
/* temporary notes */
|
||
.rfcEditorRemove::before {
|
||
position: absolute;
|
||
top: 0.2em;
|
||
right: 0.2em;
|
||
padding: 0.2em;
|
||
content: "The RFC Editor will remove this note";
|
||
color: #9e2a00; /* Arlen: WCAG 2019 */
|
||
background-color: #ffd; /* Arlen: WCAG 2019 */
|
||
}
|
||
.rfcEditorRemove {
|
||
position: relative;
|
||
padding-top: 1.8em;
|
||
background-color: #ffd; /* Arlen: WCAG 2019 */
|
||
border-radius: 3px;
|
||
}
|
||
.cref {
|
||
background-color: #ffd; /* Arlen: WCAG 2019 */
|
||
padding: 2px 4px;
|
||
}
|
||
.crefSource {
|
||
font-style: italic;
|
||
}
|
||
/* alternative layout for smaller screens */
|
||
@media screen and (max-width: 1023px) {
|
||
body {
|
||
padding-top: 2em;
|
||
}
|
||
#title {
|
||
padding: 1em 0;
|
||
}
|
||
h1 {
|
||
font-size: 24px;
|
||
}
|
||
h2 {
|
||
font-size: 20px;
|
||
margin-top: -18px; /* provide offset for in-page anchors */
|
||
padding-top: 38px;
|
||
}
|
||
#identifiers dd {
|
||
max-width: 60%;
|
||
}
|
||
#toc {
|
||
position: fixed;
|
||
z-index: 2;
|
||
top: 0;
|
||
right: 0;
|
||
padding: 0;
|
||
margin: 0;
|
||
background-color: inherit;
|
||
border-bottom: 1px solid #ccc;
|
||
}
|
||
#toc h2 {
|
||
margin: -1px 0 0 0;
|
||
padding: 4px 0 4px 6px;
|
||
padding-right: 1em;
|
||
min-width: 190px;
|
||
font-size: 1.1em;
|
||
text-align: right;
|
||
background-color: #444;
|
||
color: white;
|
||
cursor: pointer;
|
||
}
|
||
#toc h2::before { /* css hamburger */
|
||
float: right;
|
||
position: relative;
|
||
width: 1em;
|
||
height: 1px;
|
||
left: -164px;
|
||
margin: 6px 0 0 0;
|
||
background: white none repeat scroll 0 0;
|
||
box-shadow: 0 4px 0 0 white, 0 8px 0 0 white;
|
||
content: "";
|
||
}
|
||
#toc nav {
|
||
display: none;
|
||
padding: 0.5em 1em 1em;
|
||
overflow: auto;
|
||
height: calc(100vh - 48px);
|
||
border-left: 1px solid #ddd;
|
||
}
|
||
}
|
||
|
||
/* alternative layout for wide screens */
|
||
@media screen and (min-width: 1024px) {
|
||
body {
|
||
max-width: 724px;
|
||
margin: 42px auto;
|
||
padding-left: 1.5em;
|
||
padding-right: 29em;
|
||
}
|
||
#toc {
|
||
position: fixed;
|
||
top: 42px;
|
||
right: 42px;
|
||
width: 25%;
|
||
margin: 0;
|
||
padding: 0 1em;
|
||
z-index: 1;
|
||
}
|
||
#toc h2 {
|
||
border-top: none;
|
||
border-bottom: 1px solid #ddd;
|
||
font-size: 1em;
|
||
font-weight: normal;
|
||
margin: 0;
|
||
padding: 0.25em 1em 1em 0;
|
||
}
|
||
#toc nav {
|
||
display: block;
|
||
height: calc(90vh - 84px);
|
||
bottom: 0;
|
||
padding: 0.5em 0 0;
|
||
overflow: auto;
|
||
}
|
||
img { /* future proofing */
|
||
max-width: 100%;
|
||
height: auto;
|
||
}
|
||
}
|
||
|
||
/* pagination */
|
||
@media print {
|
||
body {
|
||
width: 100%;
|
||
}
|
||
p {
|
||
orphans: 3;
|
||
widows: 3;
|
||
}
|
||
#n-copyright-notice {
|
||
border-bottom: none;
|
||
}
|
||
#toc, #n-introduction {
|
||
page-break-before: always;
|
||
}
|
||
#toc {
|
||
border-top: none;
|
||
padding-top: 0;
|
||
}
|
||
figure, pre {
|
||
page-break-inside: avoid;
|
||
}
|
||
figure {
|
||
overflow: scroll;
|
||
}
|
||
.breakable pre {
|
||
break-inside: auto;
|
||
}
|
||
h1, h2, h3, h4, h5, h6 {
|
||
page-break-after: avoid;
|
||
}
|
||
h2+*, h3+*, h4+*, h5+*, h6+* {
|
||
page-break-before: avoid;
|
||
}
|
||
pre {
|
||
white-space: pre-wrap;
|
||
word-wrap: break-word;
|
||
font-size: 10pt;
|
||
}
|
||
table {
|
||
border: 1px solid #ddd;
|
||
}
|
||
td {
|
||
border-top: 1px solid #ddd;
|
||
}
|
||
}
|
||
|
||
/* This is commented out here, as the string-set: doesn't
|
||
pass W3C validation currently */
|
||
/*
|
||
.ears thead .left {
|
||
string-set: ears-top-left content();
|
||
}
|
||
|
||
.ears thead .center {
|
||
string-set: ears-top-center content();
|
||
}
|
||
|
||
.ears thead .right {
|
||
string-set: ears-top-right content();
|
||
}
|
||
|
||
.ears tfoot .left {
|
||
string-set: ears-bottom-left content();
|
||
}
|
||
|
||
.ears tfoot .center {
|
||
string-set: ears-bottom-center content();
|
||
}
|
||
|
||
.ears tfoot .right {
|
||
string-set: ears-bottom-right content();
|
||
}
|
||
*/
|
||
|
||
@page :first {
|
||
padding-top: 0;
|
||
@top-left {
|
||
content: normal;
|
||
border: none;
|
||
}
|
||
@top-center {
|
||
content: normal;
|
||
border: none;
|
||
}
|
||
@top-right {
|
||
content: normal;
|
||
border: none;
|
||
}
|
||
}
|
||
|
||
@page {
|
||
size: A4;
|
||
margin-bottom: 45mm;
|
||
padding-top: 20px;
|
||
/* The following is commented out here, but set appropriately by in code, as
|
||
the content depends on the document */
|
||
/*
|
||
@top-left {
|
||
content: 'Internet-Draft';
|
||
vertical-align: bottom;
|
||
border-bottom: solid 1px #ccc;
|
||
}
|
||
@top-left {
|
||
content: string(ears-top-left);
|
||
vertical-align: bottom;
|
||
border-bottom: solid 1px #ccc;
|
||
}
|
||
@top-center {
|
||
content: string(ears-top-center);
|
||
vertical-align: bottom;
|
||
border-bottom: solid 1px #ccc;
|
||
}
|
||
@top-right {
|
||
content: string(ears-top-right);
|
||
vertical-align: bottom;
|
||
border-bottom: solid 1px #ccc;
|
||
}
|
||
@bottom-left {
|
||
content: string(ears-bottom-left);
|
||
vertical-align: top;
|
||
border-top: solid 1px #ccc;
|
||
}
|
||
@bottom-center {
|
||
content: string(ears-bottom-center);
|
||
vertical-align: top;
|
||
border-top: solid 1px #ccc;
|
||
}
|
||
@bottom-right {
|
||
content: '[Page ' counter(page) ']';
|
||
vertical-align: top;
|
||
border-top: solid 1px #ccc;
|
||
}
|
||
*/
|
||
|
||
}
|
||
|
||
/* Changes introduced to fix issues found during implementation */
|
||
/* Make sure links are clickable even if overlapped by following H* */
|
||
a {
|
||
z-index: 2;
|
||
}
|
||
/* Separate body from document info even without intervening H1 */
|
||
section {
|
||
clear: both;
|
||
}
|
||
|
||
|
||
/* Top align author divs, to avoid names without organization dropping level with org names */
|
||
.author {
|
||
vertical-align: top;
|
||
}
|
||
|
||
/* Leave room in document info to show Internet-Draft on one line */
|
||
#identifiers dt {
|
||
width: 8em;
|
||
}
|
||
|
||
/* Don't waste quite as much whitespace between label and value in doc info */
|
||
#identifiers dd {
|
||
margin-left: 1em;
|
||
}
|
||
|
||
/* Give floating toc a background color (needed when it's a div inside section */
|
||
#toc {
|
||
background-color: white;
|
||
}
|
||
|
||
/* Make the collapsed ToC header render white on gray also when it's a link */
|
||
@media screen and (max-width: 1023px) {
|
||
#toc h2 a,
|
||
#toc h2 a:link,
|
||
#toc h2 a:focus,
|
||
#toc h2 a:hover,
|
||
#toc a.toplink,
|
||
#toc a.toplink:hover {
|
||
color: white;
|
||
background-color: #444;
|
||
text-decoration: none;
|
||
}
|
||
}
|
||
|
||
/* Give the bottom of the ToC some whitespace */
|
||
@media screen and (min-width: 1024px) {
|
||
#toc {
|
||
padding: 0 0 1em 1em;
|
||
}
|
||
}
|
||
|
||
/* Style section numbers with more space between number and title */
|
||
.section-number {
|
||
padding-right: 0.5em;
|
||
}
|
||
|
||
/* prevent monospace from becoming overly large */
|
||
tt, code, pre {
|
||
font-size: 95%;
|
||
}
|
||
|
||
/* Fix the height/width aspect for ascii art*/
|
||
.sourcecode pre,
|
||
.art-text pre {
|
||
line-height: 1.12;
|
||
}
|
||
|
||
|
||
/* Add styling for a link in the ToC that points to the top of the document */
|
||
a.toplink {
|
||
float: right;
|
||
margin-right: 0.5em;
|
||
}
|
||
|
||
/* Fix the dl styling to match the RFC 7992 attributes */
|
||
dl > dt,
|
||
dl.dlParallel > dt {
|
||
float: left;
|
||
margin-right: 1em;
|
||
}
|
||
dl.dlNewline > dt {
|
||
float: none;
|
||
}
|
||
|
||
/* Provide styling for table cell text alignment */
|
||
table td.text-left,
|
||
table th.text-left {
|
||
text-align: left;
|
||
}
|
||
table td.text-center,
|
||
table th.text-center {
|
||
text-align: center;
|
||
}
|
||
table td.text-right,
|
||
table th.text-right {
|
||
text-align: right;
|
||
}
|
||
|
||
/* Make the alternative author contact information look less like just another
|
||
author, and group it closer with the primary author contact information */
|
||
.alternative-contact {
|
||
margin: 0.5em 0 0.25em 0;
|
||
}
|
||
address .non-ascii {
|
||
margin: 0 0 0 2em;
|
||
}
|
||
|
||
/* With it being possible to set tables with alignment
|
||
left, center, and right, { width: 100%; } does not make sense */
|
||
table {
|
||
width: auto;
|
||
}
|
||
|
||
/* Avoid reference text that sits in a block with very wide left margin,
|
||
because of a long floating dt label.*/
|
||
.references dd {
|
||
overflow: visible;
|
||
}
|
||
|
||
/* Control caption placement */
|
||
caption {
|
||
caption-side: bottom;
|
||
}
|
||
|
||
/* Limit the width of the author address vcard, so names in right-to-left
|
||
script don't end up on the other side of the page. */
|
||
|
||
address.vcard {
|
||
max-width: 30em;
|
||
margin-right: auto;
|
||
}
|
||
|
||
/* For address alignment dependent on LTR or RTL scripts */
|
||
address div.left {
|
||
text-align: left;
|
||
}
|
||
address div.right {
|
||
text-align: right;
|
||
}
|
||
|
||
/* Provide table alignment support. We can't use the alignX classes above
|
||
since they do unwanted things with caption and other styling. */
|
||
table.right {
|
||
margin-left: auto;
|
||
margin-right: 0;
|
||
}
|
||
table.center {
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
table.left {
|
||
margin-left: 0;
|
||
margin-right: auto;
|
||
}
|
||
|
||
/* Give the table caption label the same styling as the figcaption */
|
||
caption a[href] {
|
||
color: #222;
|
||
}
|
||
|
||
@media print {
|
||
.toplink {
|
||
display: none;
|
||
}
|
||
|
||
/* avoid overwriting the top border line with the ToC header */
|
||
#toc {
|
||
padding-top: 1px;
|
||
}
|
||
|
||
/* Avoid page breaks inside dl and author address entries */
|
||
.vcard {
|
||
page-break-inside: avoid;
|
||
}
|
||
|
||
}
|
||
/* Tweak the bcp14 keyword presentation */
|
||
.bcp14 {
|
||
font-variant: small-caps;
|
||
font-weight: bold;
|
||
font-size: 0.9em;
|
||
}
|
||
/* Tweak the invisible space above H* in order not to overlay links in text above */
|
||
h2 {
|
||
margin-top: -18px; /* provide offset for in-page anchors */
|
||
padding-top: 31px;
|
||
}
|
||
h3 {
|
||
margin-top: -18px; /* provide offset for in-page anchors */
|
||
padding-top: 24px;
|
||
}
|
||
h4 {
|
||
margin-top: -18px; /* provide offset for in-page anchors */
|
||
padding-top: 24px;
|
||
}
|
||
/* Float artwork pilcrow to the right */
|
||
@media screen {
|
||
.artwork a.pilcrow {
|
||
display: block;
|
||
line-height: 0.7;
|
||
margin-top: 0.15em;
|
||
}
|
||
}
|
||
/* Make pilcrows on dd visible */
|
||
@media screen {
|
||
dd:hover > a.pilcrow {
|
||
visibility: visible;
|
||
}
|
||
}
|
||
/* Make the placement of figcaption match that of a table's caption
|
||
by removing the figure's added bottom margin */
|
||
.alignLeft.art-text,
|
||
.alignCenter.art-text,
|
||
.alignRight.art-text {
|
||
margin-bottom: 0;
|
||
}
|
||
.alignLeft,
|
||
.alignCenter,
|
||
.alignRight {
|
||
margin: 1em 0 0 0;
|
||
}
|
||
/* In print, the pilcrow won't show on hover, so prevent it from taking up space,
|
||
possibly even requiring a new line */
|
||
@media print {
|
||
a.pilcrow {
|
||
display: none;
|
||
}
|
||
}
|
||
/* Styling for the external metadata */
|
||
div#external-metadata {
|
||
background-color: #eee;
|
||
padding: 0.5em;
|
||
margin-bottom: 0.5em;
|
||
display: none;
|
||
}
|
||
div#internal-metadata {
|
||
padding: 0.5em; /* to match the external-metadata padding */
|
||
}
|
||
/* Styling for title RFC Number */
|
||
h1#rfcnum {
|
||
clear: both;
|
||
margin: 0 0 -1em;
|
||
padding: 1em 0 0 0;
|
||
}
|
||
/* Make .olPercent look the same as <ol><li> */
|
||
dl.olPercent > dd {
|
||
margin-bottom: 0.25em;
|
||
min-height: initial;
|
||
}
|
||
/* Give aside some styling to set it apart */
|
||
aside {
|
||
border-left: 1px solid #ddd;
|
||
margin: 1em 0 1em 2em;
|
||
padding: 0.2em 2em;
|
||
}
|
||
aside > dl,
|
||
aside > ol,
|
||
aside > ul,
|
||
aside > table,
|
||
aside > p {
|
||
margin-bottom: 0.5em;
|
||
}
|
||
/* Additional page break settings */
|
||
@media print {
|
||
figcaption, table caption {
|
||
page-break-before: avoid;
|
||
}
|
||
}
|
||
/* Font size adjustments for print */
|
||
@media print {
|
||
body { font-size: 10pt; line-height: normal; max-width: 96%; }
|
||
h1 { font-size: 1.72em; padding-top: 1.5em; } /* 1*1.2*1.2*1.2 */
|
||
h2 { font-size: 1.44em; padding-top: 1.5em; } /* 1*1.2*1.2 */
|
||
h3 { font-size: 1.2em; padding-top: 1.5em; } /* 1*1.2 */
|
||
h4 { font-size: 1em; padding-top: 1.5em; }
|
||
h5, h6 { font-size: 1em; margin: initial; padding: 0.5em 0 0.3em; }
|
||
}
|
||
/* Sourcecode margin in print, when there's no pilcrow */
|
||
@media print {
|
||
.artwork,
|
||
.artwork > pre,
|
||
.sourcecode {
|
||
margin-bottom: 1em;
|
||
}
|
||
}
|
||
/* Avoid narrow tables forcing too narrow table captions, which may render badly */
|
||
table {
|
||
min-width: 20em;
|
||
}
|
||
/* ol type a */
|
||
ol.type-a { list-style-type: lower-alpha; }
|
||
ol.type-A { list-style-type: upper-alpha; }
|
||
ol.type-i { list-style-type: lower-roman; }
|
||
ol.type-I { list-style-type: upper-roman; }
|
||
/* Apply the print table and row borders in general, on request from the RPC,
|
||
and increase the contrast between border and odd row background slightly */
|
||
table {
|
||
border: 1px solid #ddd;
|
||
}
|
||
td {
|
||
border-top: 1px solid #ddd;
|
||
}
|
||
tr {
|
||
break-inside: avoid;
|
||
}
|
||
tr:nth-child(2n+1) > td {
|
||
background-color: #f8f8f8;
|
||
}
|
||
/* Use style rules to govern display of the TOC. */
|
||
@media screen and (max-width: 1023px) {
|
||
#toc nav { display: none; }
|
||
#toc.active nav { display: block; }
|
||
}
|
||
/* Add support for keepWithNext */
|
||
.keepWithNext {
|
||
break-after: avoid-page;
|
||
break-after: avoid-page;
|
||
}
|
||
/* Add support for keepWithPrevious */
|
||
.keepWithPrevious {
|
||
break-before: avoid-page;
|
||
}
|
||
/* Change the approach to avoiding breaks inside artwork etc. */
|
||
figure, pre, table, .artwork, .sourcecode {
|
||
break-before: auto;
|
||
break-after: auto;
|
||
}
|
||
/* Avoid breaks between <dt> and <dd> */
|
||
dl {
|
||
break-before: auto;
|
||
break-inside: auto;
|
||
}
|
||
dt {
|
||
break-before: auto;
|
||
break-after: avoid-page;
|
||
}
|
||
dd {
|
||
break-before: avoid-page;
|
||
break-after: auto;
|
||
orphans: 3;
|
||
widows: 3
|
||
}
|
||
span.break, dd.break {
|
||
margin-bottom: 0;
|
||
min-height: 0;
|
||
break-before: auto;
|
||
break-inside: auto;
|
||
break-after: auto;
|
||
}
|
||
/* Undo break-before ToC */
|
||
@media print {
|
||
#toc {
|
||
break-before: auto;
|
||
}
|
||
}
|
||
/* Text in compact lists should not get extra bottom margin space,
|
||
since that would makes the list not compact */
|
||
ul.compact p, .ulCompact p,
|
||
ol.compact p, .olCompact p {
|
||
margin: 0;
|
||
}
|
||
/* But the list as a whole needs the extra space at the end */
|
||
section ul.compact,
|
||
section .ulCompact,
|
||
section ol.compact,
|
||
section .olCompact {
|
||
margin-bottom: 1em; /* same as p not within ul.compact etc. */
|
||
}
|
||
/* The tt and code background above interferes with for instance table cell
|
||
backgrounds. Changed to something a bit more selective. */
|
||
tt, code {
|
||
background-color: transparent;
|
||
}
|
||
p tt, p code, li tt, li code, dt tt, dt code {
|
||
background-color: #f8f8f8;
|
||
}
|
||
/* Tweak the pre margin -- 0px doesn't come out well */
|
||
pre {
|
||
margin-top: 0.5px;
|
||
}
|
||
/* Tweak the compact list text */
|
||
ul.compact, .ulCompact,
|
||
ol.compact, .olCompact,
|
||
dl.compact, .dlCompact {
|
||
line-height: normal;
|
||
}
|
||
/* Don't add top margin for nested lists */
|
||
li > ul, li > ol, li > dl,
|
||
dd > ul, dd > ol, dd > dl,
|
||
dl > dd > dl {
|
||
margin-top: initial;
|
||
}
|
||
/* Elements that should not be rendered on the same line as a <dt> */
|
||
/* This should match the element list in writer.text.TextWriter.render_dl() */
|
||
dd > div.artwork:first-child,
|
||
dd > aside:first-child,
|
||
dd > blockquote:first-child,
|
||
dd > figure:first-child,
|
||
dd > ol:first-child,
|
||
dd > div.sourcecode:first-child,
|
||
dd > table:first-child,
|
||
dd > ul:first-child {
|
||
clear: left;
|
||
}
|
||
/* fix for weird browser behaviour when <dd/> is empty */
|
||
dt+dd:empty::before{
|
||
content: "\00a0";
|
||
}
|
||
/* Make paragraph spacing inside <li> smaller than in body text, to fit better within the list */
|
||
li > p {
|
||
margin-bottom: 0.5em
|
||
}
|
||
/* Don't let p margin spill out from inside list items */
|
||
li > p:last-of-type:only-child {
|
||
margin-bottom: 0;
|
||
}
|
||
</style>
|
||
<link href="rfc-local.css" rel="stylesheet" type="text/css">
|
||
<link href="https://datatracker.ietf.org/doc/draft-irtf-cfrg-opaque-18" rel="prev">
|
||
<link href="https://dx.doi.org/10.17487/rfc9807" rel="alternate">
|
||
<link href="urn:issn:2070-1721" rel="alternate">
|
||
</head>
|
||
<body class="xml2rfc">
|
||
<script src="https://www.rfc-editor.org/js/metadata.min.js"></script>
|
||
<table class="ears">
|
||
<thead><tr>
|
||
<td class="left">RFC 9807</td>
|
||
<td class="center">OPAQUE</td>
|
||
<td class="right">July 2025</td>
|
||
</tr></thead>
|
||
<tfoot><tr>
|
||
<td class="left">Bourdrez, et al.</td>
|
||
<td class="center">Informational</td>
|
||
<td class="right">[Page]</td>
|
||
</tr></tfoot>
|
||
</table>
|
||
<div id="external-metadata" class="document-information"></div>
|
||
<div id="internal-metadata" class="document-information">
|
||
<dl id="identifiers">
|
||
<dt class="label-stream">Stream:</dt>
|
||
<dd class="stream">Internet Research Task Force (IRTF)</dd>
|
||
<dt class="label-rfc">RFC:</dt>
|
||
<dd class="rfc"><a href="https://www.rfc-editor.org/rfc/rfc9807" class="eref">9807</a></dd>
|
||
<dt class="label-category">Category:</dt>
|
||
<dd class="category">Informational</dd>
|
||
<dt class="label-published">Published:</dt>
|
||
<dd class="published">
|
||
<time datetime="2025-07" class="published">July 2025</time>
|
||
</dd>
|
||
<dt class="label-issn">ISSN:</dt>
|
||
<dd class="issn">2070-1721</dd>
|
||
<dt class="label-authors">Authors:</dt>
|
||
<dd class="authors">
|
||
<div class="author">
|
||
<div class="author-name">D. Bourdrez</div>
|
||
</div>
|
||
<div class="author">
|
||
<div class="author-name">H. Krawczyk</div>
|
||
<div class="org">AWS</div>
|
||
</div>
|
||
<div class="author">
|
||
<div class="author-name">K. Lewi</div>
|
||
<div class="org">Meta</div>
|
||
</div>
|
||
<div class="author">
|
||
<div class="author-name">C. A. Wood</div>
|
||
<div class="org">Cloudflare, Inc.</div>
|
||
</div>
|
||
</dd>
|
||
</dl>
|
||
</div>
|
||
<h1 id="rfcnum">RFC 9807</h1>
|
||
<h1 id="title">The OPAQUE Augmented Password-Authenticated Key Exchange (aPAKE) Protocol</h1>
|
||
<section id="section-abstract">
|
||
<h2 id="abstract"><a href="#abstract" class="selfRef">Abstract</a></h2>
|
||
<p id="section-abstract-1">This document describes the OPAQUE protocol, an Augmented (or Asymmetric)
|
||
Password-Authenticated Key Exchange (aPAKE) protocol that supports mutual
|
||
authentication in a client-server setting without reliance on PKI and
|
||
with security against pre-computation attacks upon server compromise.
|
||
In addition, the protocol provides forward secrecy and the ability to
|
||
hide the password from the server, even during password registration.
|
||
This document specifies the core OPAQUE protocol and one instantiation
|
||
based on 3DH. This document is a product of the Crypto Forum Research
|
||
Group (CFRG) in the IRTF.<a href="#section-abstract-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
<div id="status-of-memo">
|
||
<section id="section-boilerplate.1">
|
||
<h2 id="name-status-of-this-memo">
|
||
<a href="#name-status-of-this-memo" class="section-name selfRef">Status of This Memo</a>
|
||
</h2>
|
||
<p id="section-boilerplate.1-1">
|
||
This document is not an Internet Standards Track specification; it is
|
||
published for informational purposes.<a href="#section-boilerplate.1-1" class="pilcrow">¶</a></p>
|
||
<p id="section-boilerplate.1-2">
|
||
This document is a product of the Internet Research Task Force
|
||
(IRTF). The IRTF publishes the results of Internet-related
|
||
research and development activities. These results might not be
|
||
suitable for deployment. This RFC represents the consensus of the Crypto Forum
|
||
Research Group of the Internet Research Task Force (IRTF).
|
||
Documents approved for publication by the IRSG are not
|
||
candidates for any level of Internet Standard; see Section 2 of RFC
|
||
7841.<a href="#section-boilerplate.1-2" class="pilcrow">¶</a></p>
|
||
<p id="section-boilerplate.1-3">
|
||
Information about the current status of this document, any
|
||
errata, and how to provide feedback on it may be obtained at
|
||
<span><a href="https://www.rfc-editor.org/info/rfc9807">https://www.rfc-editor.org/info/rfc9807</a></span>.<a href="#section-boilerplate.1-3" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="copyright">
|
||
<section id="section-boilerplate.2">
|
||
<h2 id="name-copyright-notice">
|
||
<a href="#name-copyright-notice" class="section-name selfRef">Copyright Notice</a>
|
||
</h2>
|
||
<p id="section-boilerplate.2-1">
|
||
Copyright (c) 2025 IETF Trust and the persons identified as the
|
||
document authors. All rights reserved.<a href="#section-boilerplate.2-1" class="pilcrow">¶</a></p>
|
||
<p id="section-boilerplate.2-2">
|
||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||
Provisions Relating to IETF Documents
|
||
(<span><a href="https://trustee.ietf.org/license-info">https://trustee.ietf.org/license-info</a></span>) in effect on the date of
|
||
publication of this document. Please review these documents
|
||
carefully, as they describe your rights and restrictions with
|
||
respect to this document.<a href="#section-boilerplate.2-2" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="toc">
|
||
<section id="section-toc.1">
|
||
<a href="#" onclick="scroll(0,0)" class="toplink">▲</a><h2 id="name-table-of-contents">
|
||
<a href="#name-table-of-contents" class="section-name selfRef">Table of Contents</a>
|
||
</h2>
|
||
<nav class="toc"><ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.1">
|
||
<p id="section-toc.1-1.1.1" class="keepWithNext"><a href="#section-1" class="auto internal xref">1</a>. <a href="#name-introduction" class="internal xref">Introduction</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.1.2.1">
|
||
<p id="section-toc.1-1.1.2.1.1" class="keepWithNext"><a href="#section-1.1" class="auto internal xref">1.1</a>. <a href="#name-requirements-notation" class="internal xref">Requirements Notation</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.1.2.2">
|
||
<p id="section-toc.1-1.1.2.2.1" class="keepWithNext"><a href="#section-1.2" class="auto internal xref">1.2</a>. <a href="#name-notation" class="internal xref">Notation</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.2">
|
||
<p id="section-toc.1-1.2.1"><a href="#section-2" class="auto internal xref">2</a>. <a href="#name-cryptographic-dependencies" class="internal xref">Cryptographic Dependencies</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.2.2.1">
|
||
<p id="section-toc.1-1.2.2.1.1"><a href="#section-2.1" class="auto internal xref">2.1</a>. <a href="#name-oblivious-pseudorandom-func" class="internal xref">Oblivious Pseudorandom Function</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.2.2.2">
|
||
<p id="section-toc.1-1.2.2.2.1"><a href="#section-2.2" class="auto internal xref">2.2</a>. <a href="#name-key-derivation-function-and" class="internal xref">Key Derivation Function and Message Authentication Code</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.2.2.3">
|
||
<p id="section-toc.1-1.2.2.3.1"><a href="#section-2.3" class="auto internal xref">2.3</a>. <a href="#name-hash-functions" class="internal xref">Hash Functions</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.3">
|
||
<p id="section-toc.1-1.3.1"><a href="#section-3" class="auto internal xref">3</a>. <a href="#name-protocol-overview" class="internal xref">Protocol Overview</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.3.2.1">
|
||
<p id="section-toc.1-1.3.2.1.1"><a href="#section-3.1" class="auto internal xref">3.1</a>. <a href="#name-setup" class="internal xref">Setup</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.3.2.2">
|
||
<p id="section-toc.1-1.3.2.2.1"><a href="#section-3.2" class="auto internal xref">3.2</a>. <a href="#name-registration" class="internal xref">Registration</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.3.2.3">
|
||
<p id="section-toc.1-1.3.2.3.1"><a href="#section-3.3" class="auto internal xref">3.3</a>. <a href="#name-online-authenticated-key-ex" class="internal xref">Online Authenticated Key Exchange</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4">
|
||
<p id="section-toc.1-1.4.1"><a href="#section-4" class="auto internal xref">4</a>. <a href="#name-client-credential-storage-a" class="internal xref">Client Credential Storage and Key Recovery</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.1">
|
||
<p id="section-toc.1-1.4.2.1.1"><a href="#section-4.1" class="auto internal xref">4.1</a>. <a href="#name-key-recovery" class="internal xref">Key Recovery</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.1.2.1">
|
||
<p id="section-toc.1-1.4.2.1.2.1.1"><a href="#section-4.1.1" class="auto internal xref">4.1.1</a>. <a href="#name-envelope-structure" class="internal xref">Envelope Structure</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.1.2.2">
|
||
<p id="section-toc.1-1.4.2.1.2.2.1"><a href="#section-4.1.2" class="auto internal xref">4.1.2</a>. <a href="#name-envelope-creation" class="internal xref">Envelope Creation</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.4.2.1.2.3">
|
||
<p id="section-toc.1-1.4.2.1.2.3.1"><a href="#section-4.1.3" class="auto internal xref">4.1.3</a>. <a href="#name-envelope-recovery" class="internal xref">Envelope Recovery</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.5">
|
||
<p id="section-toc.1-1.5.1"><a href="#section-5" class="auto internal xref">5</a>. <a href="#name-registration-2" class="internal xref">Registration</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.5.2.1">
|
||
<p id="section-toc.1-1.5.2.1.1"><a href="#section-5.1" class="auto internal xref">5.1</a>. <a href="#name-registration-messages" class="internal xref">Registration Messages</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.5.2.2">
|
||
<p id="section-toc.1-1.5.2.2.1"><a href="#section-5.2" class="auto internal xref">5.2</a>. <a href="#name-registration-functions" class="internal xref">Registration Functions</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.5.2.2.2.1">
|
||
<p id="section-toc.1-1.5.2.2.2.1.1"><a href="#section-5.2.1" class="auto internal xref">5.2.1</a>. <a href="#name-createregistrationrequest" class="internal xref">CreateRegistrationRequest</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.5.2.2.2.2">
|
||
<p id="section-toc.1-1.5.2.2.2.2.1"><a href="#section-5.2.2" class="auto internal xref">5.2.2</a>. <a href="#name-createregistrationresponse" class="internal xref">CreateRegistrationResponse</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.5.2.2.2.3">
|
||
<p id="section-toc.1-1.5.2.2.2.3.1"><a href="#section-5.2.3" class="auto internal xref">5.2.3</a>. <a href="#name-finalizeregistrationrequest" class="internal xref">FinalizeRegistrationRequest</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6">
|
||
<p id="section-toc.1-1.6.1"><a href="#section-6" class="auto internal xref">6</a>. <a href="#name-online-authenticated-key-exc" class="internal xref">Online Authenticated Key Exchange</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.1">
|
||
<p id="section-toc.1-1.6.2.1.1"><a href="#section-6.1" class="auto internal xref">6.1</a>. <a href="#name-ake-messages" class="internal xref">AKE Messages</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.2">
|
||
<p id="section-toc.1-1.6.2.2.1"><a href="#section-6.2" class="auto internal xref">6.2</a>. <a href="#name-ake-functions" class="internal xref">AKE Functions</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.2.2.1">
|
||
<p id="section-toc.1-1.6.2.2.2.1.1"><a href="#section-6.2.1" class="auto internal xref">6.2.1</a>. <a href="#name-generateke1" class="internal xref">GenerateKE1</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.2.2.2">
|
||
<p id="section-toc.1-1.6.2.2.2.2.1"><a href="#section-6.2.2" class="auto internal xref">6.2.2</a>. <a href="#name-generateke2" class="internal xref">GenerateKE2</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.2.2.3">
|
||
<p id="section-toc.1-1.6.2.2.2.3.1"><a href="#section-6.2.3" class="auto internal xref">6.2.3</a>. <a href="#name-generateke3" class="internal xref">GenerateKE3</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.2.2.4">
|
||
<p id="section-toc.1-1.6.2.2.2.4.1"><a href="#section-6.2.4" class="auto internal xref">6.2.4</a>. <a href="#name-serverfinish" class="internal xref">ServerFinish</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.3">
|
||
<p id="section-toc.1-1.6.2.3.1"><a href="#section-6.3" class="auto internal xref">6.3</a>. <a href="#name-credential-retrieval" class="internal xref">Credential Retrieval</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.3.2.1">
|
||
<p id="section-toc.1-1.6.2.3.2.1.1"><a href="#section-6.3.1" class="auto internal xref">6.3.1</a>. <a href="#name-credential-retrieval-messag" class="internal xref">Credential Retrieval Messages</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.3.2.2">
|
||
<p id="section-toc.1-1.6.2.3.2.2.1"><a href="#section-6.3.2" class="auto internal xref">6.3.2</a>. <a href="#name-credential-retrieval-functi" class="internal xref">Credential Retrieval Functions</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.4">
|
||
<p id="section-toc.1-1.6.2.4.1"><a href="#section-6.4" class="auto internal xref">6.4</a>. <a href="#name-3dh-protocol" class="internal xref">3DH Protocol</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.4.2.1">
|
||
<p id="section-toc.1-1.6.2.4.2.1.1"><a href="#section-6.4.1" class="auto internal xref">6.4.1</a>. <a href="#name-3dh-key-exchange-functions" class="internal xref">3DH Key Exchange Functions</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.4.2.2">
|
||
<p id="section-toc.1-1.6.2.4.2.2.1"><a href="#section-6.4.2" class="auto internal xref">6.4.2</a>. <a href="#name-key-schedule-functions" class="internal xref">Key Schedule Functions</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.4.2.3">
|
||
<p id="section-toc.1-1.6.2.4.2.3.1"><a href="#section-6.4.3" class="auto internal xref">6.4.3</a>. <a href="#name-3dh-client-functions" class="internal xref">3DH Client Functions</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.6.2.4.2.4">
|
||
<p id="section-toc.1-1.6.2.4.2.4.1"><a href="#section-6.4.4" class="auto internal xref">6.4.4</a>. <a href="#name-3dh-server-functions" class="internal xref">3DH Server Functions</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.7">
|
||
<p id="section-toc.1-1.7.1"><a href="#section-7" class="auto internal xref">7</a>. <a href="#name-configurations" class="internal xref">Configurations</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.8">
|
||
<p id="section-toc.1-1.8.1"><a href="#section-8" class="auto internal xref">8</a>. <a href="#name-application-considerations" class="internal xref">Application Considerations</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.9">
|
||
<p id="section-toc.1-1.9.1"><a href="#section-9" class="auto internal xref">9</a>. <a href="#name-implementation-consideratio" class="internal xref">Implementation Considerations</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.9.2.1">
|
||
<p id="section-toc.1-1.9.2.1.1"><a href="#section-9.1" class="auto internal xref">9.1</a>. <a href="#name-implementation-safeguards" class="internal xref">Implementation Safeguards</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.9.2.2">
|
||
<p id="section-toc.1-1.9.2.2.1"><a href="#section-9.2" class="auto internal xref">9.2</a>. <a href="#name-handling-online-guessing-at" class="internal xref">Handling Online Guessing Attacks</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.9.2.3">
|
||
<p id="section-toc.1-1.9.2.3.1"><a href="#section-9.3" class="auto internal xref">9.3</a>. <a href="#name-error-considerations" class="internal xref">Error Considerations</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10">
|
||
<p id="section-toc.1-1.10.1"><a href="#section-10" class="auto internal xref">10</a>. <a href="#name-security-considerations" class="internal xref">Security Considerations</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.1">
|
||
<p id="section-toc.1-1.10.2.1.1"><a href="#section-10.1" class="auto internal xref">10.1</a>. <a href="#name-notable-design-differences" class="internal xref">Notable Design Differences</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.2">
|
||
<p id="section-toc.1-1.10.2.2.1"><a href="#section-10.2" class="auto internal xref">10.2</a>. <a href="#name-security-analysis" class="internal xref">Security Analysis</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.3">
|
||
<p id="section-toc.1-1.10.2.3.1"><a href="#section-10.3" class="auto internal xref">10.3</a>. <a href="#name-identities" class="internal xref">Identities</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.4">
|
||
<p id="section-toc.1-1.10.2.4.1"><a href="#section-10.4" class="auto internal xref">10.4</a>. <a href="#name-export-key-usage" class="internal xref">Export Key Usage</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.5">
|
||
<p id="section-toc.1-1.10.2.5.1"><a href="#section-10.5" class="auto internal xref">10.5</a>. <a href="#name-static-diffie-hellman-oracl" class="internal xref">Static Diffie-Hellman Oracles</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.6">
|
||
<p id="section-toc.1-1.10.2.6.1"><a href="#section-10.6" class="auto internal xref">10.6</a>. <a href="#name-random-key-robust-macs" class="internal xref">Random-Key Robust MACs</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.7">
|
||
<p id="section-toc.1-1.10.2.7.1"><a href="#section-10.7" class="auto internal xref">10.7</a>. <a href="#name-input-validation" class="internal xref">Input Validation</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.8">
|
||
<p id="section-toc.1-1.10.2.8.1"><a href="#section-10.8" class="auto internal xref">10.8</a>. <a href="#name-oprf-key-stretching" class="internal xref">OPRF Key Stretching</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.9">
|
||
<p id="section-toc.1-1.10.2.9.1"><a href="#section-10.9" class="auto internal xref">10.9</a>. <a href="#name-client-enumeration" class="internal xref">Client Enumeration</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.10">
|
||
<p id="section-toc.1-1.10.2.10.1"><a href="#section-10.10" class="auto internal xref">10.10</a>. <a href="#name-protecting-the-registration" class="internal xref">Protecting the Registration Masking Key</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.11">
|
||
<p id="section-toc.1-1.10.2.11.1"><a href="#section-10.11" class="auto internal xref">10.11</a>. <a href="#name-password-salt-and-storage-i" class="internal xref">Password Salt and Storage Implications</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.12">
|
||
<p id="section-toc.1-1.10.2.12.1"><a href="#section-10.12" class="auto internal xref">10.12</a>. <a href="#name-ake-private-key-storage" class="internal xref">AKE Private Key Storage</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.10.2.13">
|
||
<p id="section-toc.1-1.10.2.13.1"><a href="#section-10.13" class="auto internal xref">10.13</a>. <a href="#name-client-authentication-using" class="internal xref">Client Authentication Using Credentials</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.11">
|
||
<p id="section-toc.1-1.11.1"><a href="#section-11" class="auto internal xref">11</a>. <a href="#name-iana-considerations" class="internal xref">IANA Considerations</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.12">
|
||
<p id="section-toc.1-1.12.1"><a href="#section-12" class="auto internal xref">12</a>. <a href="#name-references" class="internal xref">References</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.12.2.1">
|
||
<p id="section-toc.1-1.12.2.1.1"><a href="#section-12.1" class="auto internal xref">12.1</a>. <a href="#name-normative-references" class="internal xref">Normative References</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.12.2.2">
|
||
<p id="section-toc.1-1.12.2.2.1"><a href="#section-12.2" class="auto internal xref">12.2</a>. <a href="#name-informative-references" class="internal xref">Informative References</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.13">
|
||
<p id="section-toc.1-1.13.1"><a href="#appendix-A" class="auto internal xref">Appendix A</a>. <a href="#name-alternate-key-recovery-mech" class="internal xref">Alternate Key Recovery Mechanisms</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.14">
|
||
<p id="section-toc.1-1.14.1"><a href="#appendix-B" class="auto internal xref">Appendix B</a>. <a href="#name-alternate-ake-instantiation" class="internal xref">Alternate AKE Instantiations</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.14.2.1">
|
||
<p id="section-toc.1-1.14.2.1.1"><a href="#appendix-B.1" class="auto internal xref">B.1</a>. <a href="#name-hmqv-instantiation-sketch" class="internal xref">HMQV Instantiation Sketch</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.14.2.2">
|
||
<p id="section-toc.1-1.14.2.2.1"><a href="#appendix-B.2" class="auto internal xref">B.2</a>. <a href="#name-sigma-i-instantiation-sketc" class="internal xref">SIGMA-I Instantiation Sketch</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15">
|
||
<p id="section-toc.1-1.15.1"><a href="#appendix-C" class="auto internal xref">Appendix C</a>. <a href="#name-test-vectors" class="internal xref">Test Vectors</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.1">
|
||
<p id="section-toc.1-1.15.2.1.1"><a href="#appendix-C.1" class="auto internal xref">C.1</a>. <a href="#name-real-test-vectors" class="internal xref">Real Test Vectors</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.1.2.1">
|
||
<p id="section-toc.1-1.15.2.1.2.1.1"><a href="#appendix-C.1.1" class="auto internal xref">C.1.1</a>. <a href="#name-opaque-3dh-real-test-vector" class="internal xref">OPAQUE-3DH Real Test Vector 1</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.1.2.2">
|
||
<p id="section-toc.1-1.15.2.1.2.2.1"><a href="#appendix-C.1.2" class="auto internal xref">C.1.2</a>. <a href="#name-opaque-3dh-real-test-vector-" class="internal xref">OPAQUE-3DH Real Test Vector 2</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.1.2.3">
|
||
<p id="section-toc.1-1.15.2.1.2.3.1"><a href="#appendix-C.1.3" class="auto internal xref">C.1.3</a>. <a href="#name-opaque-3dh-real-test-vector-3" class="internal xref">OPAQUE-3DH Real Test Vector 3</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.1.2.4">
|
||
<p id="section-toc.1-1.15.2.1.2.4.1"><a href="#appendix-C.1.4" class="auto internal xref">C.1.4</a>. <a href="#name-opaque-3dh-real-test-vector-4" class="internal xref">OPAQUE-3DH Real Test Vector 4</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.1.2.5">
|
||
<p id="section-toc.1-1.15.2.1.2.5.1"><a href="#appendix-C.1.5" class="auto internal xref">C.1.5</a>. <a href="#name-opaque-3dh-real-test-vector-5" class="internal xref">OPAQUE-3DH Real Test Vector 5</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.1.2.6">
|
||
<p id="section-toc.1-1.15.2.1.2.6.1"><a href="#appendix-C.1.6" class="auto internal xref">C.1.6</a>. <a href="#name-opaque-3dh-real-test-vector-6" class="internal xref">OPAQUE-3DH Real Test Vector 6</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.2">
|
||
<p id="section-toc.1-1.15.2.2.1"><a href="#appendix-C.2" class="auto internal xref">C.2</a>. <a href="#name-fake-test-vectors" class="internal xref">Fake Test Vectors</a></p>
|
||
<ul class="compact toc ulBare ulEmpty">
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.2.2.1">
|
||
<p id="section-toc.1-1.15.2.2.2.1.1"><a href="#appendix-C.2.1" class="auto internal xref">C.2.1</a>. <a href="#name-opaque-3dh-fake-test-vector" class="internal xref">OPAQUE-3DH Fake Test Vector 1</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.2.2.2">
|
||
<p id="section-toc.1-1.15.2.2.2.2.1"><a href="#appendix-C.2.2" class="auto internal xref">C.2.2</a>. <a href="#name-opaque-3dh-fake-test-vector-" class="internal xref">OPAQUE-3DH Fake Test Vector 2</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.15.2.2.2.3">
|
||
<p id="section-toc.1-1.15.2.2.2.3.1"><a href="#appendix-C.2.3" class="auto internal xref">C.2.3</a>. <a href="#name-opaque-3dh-fake-test-vector-3" class="internal xref">OPAQUE-3DH Fake Test Vector 3</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.16">
|
||
<p id="section-toc.1-1.16.1"><a href="#appendix-D" class="auto internal xref"></a><a href="#name-acknowledgments" class="internal xref">Acknowledgments</a></p>
|
||
</li>
|
||
<li class="compact toc ulBare ulEmpty" id="section-toc.1-1.17">
|
||
<p id="section-toc.1-1.17.1"><a href="#appendix-E" class="auto internal xref"></a><a href="#name-authors-addresses" class="internal xref">Authors' Addresses</a></p>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
</section>
|
||
</div>
|
||
<div id="intro">
|
||
<section id="section-1">
|
||
<h2 id="name-introduction">
|
||
<a href="#section-1" class="section-number selfRef">1. </a><a href="#name-introduction" class="section-name selfRef">Introduction</a>
|
||
</h2>
|
||
<p id="section-1-1">Password authentication is ubiquitous in many applications. In a common
|
||
implementation, a client authenticates to a server by sending its client
|
||
ID and password to the server over a secure connection. This makes
|
||
the password vulnerable to server mishandling, including accidentally
|
||
logging the password or storing it in plaintext in a database. Server
|
||
compromise resulting in access to these plaintext passwords is not an
|
||
uncommon security incident, even among security-conscious organizations. Moreover, plaintext password authentication over secure channels such as
|
||
TLS is also vulnerable in cases where TLS may fail, including PKI
|
||
attacks, certificate mishandling, termination outside the security
|
||
perimeter, visibility to TLS-terminating intermediaries, and more.<a href="#section-1-1" class="pilcrow">¶</a></p>
|
||
<p id="section-1-2">Augmented (or Asymmetric) Password Authenticated Key Exchange (aPAKE)
|
||
protocols are designed to provide password authentication and
|
||
mutually authenticated key exchange in a client-server setting without
|
||
relying on PKI (except during client registration) and without
|
||
disclosing passwords to servers or other entities other than the client
|
||
machine. A secure aPAKE should provide the best possible security for a
|
||
password protocol. Indeed, some attacks are inevitable, such as
|
||
online impersonation attempts with guessed client passwords and offline
|
||
dictionary attacks upon the compromise of a server and leakage of its
|
||
credential file. In the latter case, the attacker learns a mapping of
|
||
a client's password under a one-way function and uses such a mapping to
|
||
validate potential guesses for the password. It is crucially important for the password protocol to use an unpredictable one-way mapping.
|
||
Otherwise, the attacker can pre-compute a deterministic list of mapped
|
||
passwords leading to almost instantaneous leakage of passwords upon
|
||
server compromise.<a href="#section-1-2" class="pilcrow">¶</a></p>
|
||
<p id="section-1-3">This document describes OPAQUE, an aPAKE protocol that is secure against
|
||
pre-computation attacks (as defined in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>). OPAQUE provides forward
|
||
secrecy with respect to password leakage while also hiding the password from
|
||
the server, even during password registration. OPAQUE allows applications
|
||
to increase the difficulty of offline dictionary attacks via iterated
|
||
hashing or other key-stretching schemes. OPAQUE is also extensible, allowing
|
||
clients to safely store and retrieve arbitrary application data on servers
|
||
using only their password.<a href="#section-1-3" class="pilcrow">¶</a></p>
|
||
<p id="section-1-4">OPAQUE is defined and proven as the composition of three functionalities:
|
||
an Oblivious Pseudorandom Function (OPRF), a key recovery mechanism,
|
||
and an authenticated key exchange (AKE) protocol. It can be seen
|
||
as a "compiler" for transforming any suitable AKE protocol into a secure
|
||
aPAKE protocol. (See <a href="#security-considerations" class="auto internal xref">Section 10</a> for requirements of the
|
||
OPRF and AKE protocols.) This document specifies one OPAQUE instantiation
|
||
based on <span>[<a href="#TripleDH" class="cite xref">TripleDH</a>]</span>. Other instantiations are possible, as discussed in
|
||
<a href="#alternate-akes" class="auto internal xref">Appendix B</a>, but their details are out of scope for this document.
|
||
In general, the modularity of OPAQUE's design makes it easy to integrate with
|
||
additional AKE protocols, e.g., TLS or HMQV (Hashed Menezes-Qu-Vanstone), and
|
||
with future AKE protocols such as those based on post-quantum techniques.<a href="#section-1-4" class="pilcrow">¶</a></p>
|
||
<p id="section-1-5">OPAQUE consists of two stages: registration and authenticated key exchange.
|
||
In the first stage, a client registers its password with the server and stores
|
||
information used to recover authentication credentials on the server. Recovering these
|
||
credentials can only be done with knowledge of the client password. In the second
|
||
stage, a client uses its password to recover those credentials and subsequently
|
||
uses them as input to an AKE protocol. This stage has additional mechanisms to
|
||
prevent an active attacker from interacting with the server to guess or confirm
|
||
clients registered via the first phase. Servers can use this mechanism to safeguard
|
||
registered clients against this type of enumeration attack; see
|
||
<a href="#preventing-client-enumeration" class="auto internal xref">Section 10.9</a> for more discussion.<a href="#section-1-5" class="pilcrow">¶</a></p>
|
||
<p id="section-1-6">The name "OPAQUE" is a homonym of O-PAKE, where O is for Oblivious. The name
|
||
"OPAKE" was taken.<a href="#section-1-6" class="pilcrow">¶</a></p>
|
||
<p id="section-1-7">This document complies with the requirements for PAKE protocols set forth in
|
||
<span>[<a href="#RFC8125" class="cite xref">RFC8125</a>]</span>. This document represents the consensus of the Crypto Forum
|
||
Research Group (CFRG). It is not an IETF product and is not a standard.<a href="#section-1-7" class="pilcrow">¶</a></p>
|
||
<div id="requirements-notation">
|
||
<section id="section-1.1">
|
||
<h3 id="name-requirements-notation">
|
||
<a href="#section-1.1" class="section-number selfRef">1.1. </a><a href="#name-requirements-notation" class="section-name selfRef">Requirements Notation</a>
|
||
</h3>
|
||
<p id="section-1.1-1">
|
||
The key words "<span class="bcp14">MUST</span>", "<span class="bcp14">MUST NOT</span>", "<span class="bcp14">REQUIRED</span>", "<span class="bcp14">SHALL</span>", "<span class="bcp14">SHALL NOT</span>", "<span class="bcp14">SHOULD</span>", "<span class="bcp14">SHOULD NOT</span>", "<span class="bcp14">RECOMMENDED</span>", "<span class="bcp14">NOT RECOMMENDED</span>",
|
||
"<span class="bcp14">MAY</span>", and "<span class="bcp14">OPTIONAL</span>" in this document are to be interpreted as
|
||
described in BCP 14 <span>[<a href="#RFC2119" class="cite xref">RFC2119</a>]</span> <span>[<a href="#RFC8174" class="cite xref">RFC8174</a>]</span>
|
||
when, and only when, they appear in all capitals, as shown here.<a href="#section-1.1-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="notation">
|
||
<section id="section-1.2">
|
||
<h3 id="name-notation">
|
||
<a href="#section-1.2" class="section-number selfRef">1.2. </a><a href="#name-notation" class="section-name selfRef">Notation</a>
|
||
</h3>
|
||
<p id="section-1.2-1">The following functions are used throughout this document:<a href="#section-1.2-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-1.2-2">
|
||
<dt id="section-1.2-2.1">I2OSP and OS2IP:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-1.2-2.2">Convert a byte string to and from a non-negative
|
||
integer as described in <span><a href="https://rfc-editor.org/rfc/rfc8017#section-4" class="relref">Section 4</a> of [<a href="#RFC8017" class="cite xref">RFC8017</a>]</span>. Note
|
||
that these functions operate on byte strings in big-endian byte
|
||
order.<a href="#section-1.2-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-1.2-2.3">concat(x0, ..., xN):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-1.2-2.4">Concatenate byte strings. For example,
|
||
<code>concat(0x01, 0x0203, 0x040506) = 0x010203040506</code>.<a href="#section-1.2-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-1.2-2.5">random(n):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-1.2-2.6">Generates a cryptographically secure
|
||
pseudorandom byte string of length <code>n</code> bytes.<a href="#section-1.2-2.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-1.2-2.7">zeroes(n):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-1.2-2.8">Generate a string of <code>n</code> bytes all
|
||
equal to 0 (zero).<a href="#section-1.2-2.8" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-1.2-2.9">xor(a,b):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-1.2-2.10">Apply XOR to byte strings. For example, <code>xor(0xF0F0,
|
||
0x1234) = 0xE2C4</code>. It is an error to call this function with
|
||
arguments of unequal length.<a href="#section-1.2-2.10" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-1.2-2.11">ct_equal(a, b):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-1.2-2.12">Return <code>true</code> if <code>a</code> is equal to
|
||
<code>b</code>, and false otherwise. The implementation of this
|
||
function must be constant-time in the length of <code>a</code> and
|
||
<code>b</code>, which are assumed to be of equal length, irrespective of
|
||
the values <code>a</code> or <code>b</code>.<a href="#section-1.2-2.12" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-1.2-3">Except if said otherwise, random choices in this specification refer to
|
||
drawing with uniform distribution from a given set (i.e., "random" is short
|
||
for "uniformly random"). Random choices can be replaced with fresh outputs from
|
||
a cryptographically strong pseudorandom generator, according to the requirements
|
||
in <span>[<a href="#RFC4086" class="cite xref">RFC4086</a>]</span>, or a pseudorandom function. For convenience, we define <code>nil</code> as a
|
||
lack of value.<a href="#section-1.2-3" class="pilcrow">¶</a></p>
|
||
<p id="section-1.2-4">All protocol messages and structures defined in this document use the syntax from
|
||
<span><a href="https://rfc-editor.org/rfc/rfc8446#section-3" class="relref">Section 3</a> of [<a href="#RFC8446" class="cite xref">RFC8446</a>]</span>.<a href="#section-1.2-4" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="dependencies">
|
||
<section id="section-2">
|
||
<h2 id="name-cryptographic-dependencies">
|
||
<a href="#section-2" class="section-number selfRef">2. </a><a href="#name-cryptographic-dependencies" class="section-name selfRef">Cryptographic Dependencies</a>
|
||
</h2>
|
||
<p id="section-2-1">OPAQUE depends on the following cryptographic protocols and primitives:<a href="#section-2-1" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-2-2.1">
|
||
<p id="section-2-2.1.1">Oblivious Pseudorandom Function (OPRF); <a href="#deps-oprf" class="auto internal xref">Section 2.1</a><a href="#section-2-2.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-2-2.2">
|
||
<p id="section-2-2.2.1">Key Derivation Function (KDF); <a href="#deps-symmetric" class="auto internal xref">Section 2.2</a><a href="#section-2-2.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-2-2.3">
|
||
<p id="section-2-2.3.1">Message Authentication Code (MAC); <a href="#deps-symmetric" class="auto internal xref">Section 2.2</a><a href="#section-2-2.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-2-2.4">
|
||
<p id="section-2-2.4.1">Cryptographic Hash Function; <a href="#deps-hash" class="auto internal xref">Section 2.3</a><a href="#section-2-2.4.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-2-2.5">
|
||
<p id="section-2-2.5.1">Key Stretching Function (KSF); <a href="#deps-hash" class="auto internal xref">Section 2.3</a><a href="#section-2-2.5.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
<p id="section-2-3">This section describes these protocols and primitives in more detail. Unless said
|
||
otherwise, all random nonces and <code>seeds</code> used in these dependencies and the rest of
|
||
the OPAQUE protocol are of length <code>Nn</code> and <code>Nseed</code> bytes, respectively, where
|
||
<code>Nn</code> = <code>Nseed</code> = 32.<a href="#section-2-3" class="pilcrow">¶</a></p>
|
||
<div id="deps-oprf">
|
||
<section id="section-2.1">
|
||
<h3 id="name-oblivious-pseudorandom-func">
|
||
<a href="#section-2.1" class="section-number selfRef">2.1. </a><a href="#name-oblivious-pseudorandom-func" class="section-name selfRef">Oblivious Pseudorandom Function</a>
|
||
</h3>
|
||
<p id="section-2.1-1">An Oblivious Pseudorandom Function (OPRF) is a two-party protocol between
|
||
client and server for computing a Pseudorandom Function (PRF), where the PRF key is held by the server
|
||
and the input to the function is provided by the client. The client does not
|
||
learn anything about the PRF other than the obtained output, and the server
|
||
learns nothing about the client's input or the function output.
|
||
This specification depends on the prime-order OPRF construction specified
|
||
as <code>modeOPRF</code> (<code>0x00</code>) from <span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.1" class="relref">Section 3.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>.<a href="#section-2.1-1" class="pilcrow">¶</a></p>
|
||
<p id="section-2.1-2">The following OPRF client APIs are used:<a href="#section-2.1-2" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-2.1-3">
|
||
<dt id="section-2.1-3.1">Blind(element):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-3.2">Create and output (<code>blind</code>,
|
||
<code>blinded_element</code>), consisting of a blinded representation of
|
||
input <code>element</code>, denoted <code>blinded_element</code>, along with
|
||
a value to revert the blinding process, denoted <code>blind</code>. This
|
||
is equivalent to the Blind function described in
|
||
<span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.3.1" class="relref">Section 3.3.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>.<a href="#section-2.1-3.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.1-3.3">Finalize(element, blind, evaluated_element):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-3.4">Finalize the OPRF
|
||
evaluation using input <code>element</code>, random inverter
|
||
<code>blind</code>, and evaluation output <code>evaluated_element</code>,
|
||
yielding output <code>oprf_output</code>. This is equivalent to the
|
||
Finalize function described in <span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.3.1" class="relref">Section 3.3.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>.<a href="#section-2.1-3.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-2.1-4">Moreover, the following OPRF server APIs are used:<a href="#section-2.1-4" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-2.1-5">
|
||
<dt id="section-2.1-5.1">BlindEvaluate(k, blinded_element):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-5.2">Evaluate blinded input
|
||
<code>blinded_element</code> using input key <code>k</code>, yielding output
|
||
element <code>evaluated_element</code>. This is equivalent to the
|
||
BlindEvaluate function described in <span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.3.1" class="relref">Section 3.3.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>, where <code>k</code> is the private key
|
||
parameter.<a href="#section-2.1-5.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.1-5.3">DeriveKeyPair(seed, info):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-5.4">Create and output (<code>sk</code>,
|
||
<code>pk</code>), consisting of a private and public key derived
|
||
deterministically from an input <code>seed</code> and input
|
||
<code>info</code> parameter, as described in <span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.2" class="relref">Section 3.2</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>.<a href="#section-2.1-5.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-2.1-6">Finally, this specification makes use of the following shared APIs and parameters:<a href="#section-2.1-6" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-2.1-7">
|
||
<dt id="section-2.1-7.1">SerializeElement(element):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-7.2">Map input <code>element</code> to a fixed-length byte array.<a href="#section-2.1-7.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.1-7.3">DeserializeElement(buf):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-7.4">Attempt to map input byte array
|
||
<code>buf</code> to an OPRF group element. This function can raise a
|
||
DeserializeError upon failure; see <span><a href="https://rfc-editor.org/rfc/rfc9497#section-2.1" class="relref">Section 2.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span> for more details.<a href="#section-2.1-7.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.1-7.5">Noe:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-7.6">The size of a serialized OPRF group element output from SerializeElement.<a href="#section-2.1-7.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.1-7.7">Nok:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.1-7.8">The size of an OPRF private key as output from DeriveKeyPair.<a href="#section-2.1-7.8" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="deps-symmetric">
|
||
<section id="section-2.2">
|
||
<h3 id="name-key-derivation-function-and">
|
||
<a href="#section-2.2" class="section-number selfRef">2.2. </a><a href="#name-key-derivation-function-and" class="section-name selfRef">Key Derivation Function and Message Authentication Code</a>
|
||
</h3>
|
||
<p id="section-2.2-1">A Key Derivation Function (KDF) is a function that takes some source of initial
|
||
keying material and uses it to derive one or more cryptographically strong keys.
|
||
This specification uses a KDF with the following API and parameters:<a href="#section-2.2-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-2.2-2">
|
||
<dt id="section-2.2-2.1">Extract(salt, ikm):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.2-2.2">Extract a pseudorandom key of fixed length
|
||
<code>Nx</code> bytes from input keying material <code>ikm</code> and an
|
||
optional byte string <code>salt</code>.<a href="#section-2.2-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.2-2.3">Expand(prk, info, L):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.2-2.4">Expand a pseudorandom key <code>prk</code>,
|
||
using the string <code>info</code>, into <code>L</code> bytes of output
|
||
keying material.<a href="#section-2.2-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.2-2.5">
|
||
<code>Nx</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.2-2.6">The output size of the <code>Extract()</code> function in bytes.<a href="#section-2.2-2.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-2.2-3">This specification also makes use of a random-key robust Message Authentication Code
|
||
(MAC). See <a href="#rkr-mac" class="auto internal xref">Section 10.6</a> for more details on this property. The API and parameters for
|
||
the random-key robust MAC are as follows:<a href="#section-2.2-3" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-2.2-4">
|
||
<dt id="section-2.2-4.1">MAC(key, msg):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.2-4.2">Compute a message authentication code
|
||
over input <code>msg</code> with key <code>key</code>, producing a
|
||
fixed-length output of <code>Nm</code> bytes.<a href="#section-2.2-4.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.2-4.3">
|
||
<code>Nm</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.2-4.4">The output size of the <code>MAC()</code> function in bytes.<a href="#section-2.2-4.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="deps-hash">
|
||
<section id="section-2.3">
|
||
<h3 id="name-hash-functions">
|
||
<a href="#section-2.3" class="section-number selfRef">2.3. </a><a href="#name-hash-functions" class="section-name selfRef">Hash Functions</a>
|
||
</h3>
|
||
<p id="section-2.3-1">This specification makes use of a collision-resistant hash function with the following
|
||
API and parameters:<a href="#section-2.3-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-2.3-2">
|
||
<dt id="section-2.3-2.1">Hash(msg):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.3-2.2">Apply a cryptographic hash function to input
|
||
<code>msg</code>, producing a fixed-length digest of size <code>Nh</code>
|
||
bytes.<a href="#section-2.3-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-2.3-2.3">
|
||
<code>Nh</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.3-2.4">The output size of the <code>Hash()</code> function in bytes.<a href="#section-2.3-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-2.3-3">This specification makes use of a Key Stretching Function (KSF), which is a slow
|
||
and expensive cryptographic hash function with the following API:<a href="#section-2.3-3" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-2.3-4">
|
||
<dt id="section-2.3-4.1">Stretch(msg):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-2.3-4.2">Apply a key stretching function to stretch
|
||
the input <code>msg</code> and harden it against offline dictionary
|
||
attacks. This function also needs to satisfy collision
|
||
resistance.<a href="#section-2.3-4.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="protocol-overview">
|
||
<section id="section-3">
|
||
<h2 id="name-protocol-overview">
|
||
<a href="#section-3" class="section-number selfRef">3. </a><a href="#name-protocol-overview" class="section-name selfRef">Protocol Overview</a>
|
||
</h2>
|
||
<p id="section-3-1">OPAQUE consists of two stages: registration and authenticated key exchange (AKE).
|
||
In the first stage, a client registers its password with the server and stores
|
||
its credential file on the server. In the second stage (also called the
|
||
"login" or "online" stage), the client recovers its authentication material and uses it to
|
||
perform a mutually authenticated key exchange.<a href="#section-3-1" class="pilcrow">¶</a></p>
|
||
<div id="setup">
|
||
<section id="section-3.1">
|
||
<h3 id="name-setup">
|
||
<a href="#section-3.1" class="section-number selfRef">3.1. </a><a href="#name-setup" class="section-name selfRef">Setup</a>
|
||
</h3>
|
||
<p id="section-3.1-1">Prior to both stages, the client and server agree on a configuration that
|
||
fully specifies the cryptographic algorithm dependencies necessary to run the
|
||
protocol; see <a href="#configurations" class="auto internal xref">Section 7</a> for details.
|
||
The server chooses a pair of keys (<code>server_private_key</code> and <code>server_public_key</code>)
|
||
for the AKE protocol and chooses a <code>seed</code> (<code>oprf_seed</code>) of <code>Nh</code> bytes for the OPRF.
|
||
The server can use <code>server_private_key</code> and <code>server_public_key</code> with multiple
|
||
clients. The server can also opt to use a different <code>seed</code> for each client
|
||
(i.e., each client can be assigned a single <code>seed</code>), so long as they are maintained
|
||
across the registration and online AKE stages and kept consistent for each
|
||
client (since an inconsistent mapping of clients to <code>seeds</code> could leak information
|
||
as described in <a href="#preventing-client-enumeration" class="auto internal xref">Section 10.9</a>).<a href="#section-3.1-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="registration">
|
||
<section id="section-3.2">
|
||
<h3 id="name-registration">
|
||
<a href="#section-3.2" class="section-number selfRef">3.2. </a><a href="#name-registration" class="section-name selfRef">Registration</a>
|
||
</h3>
|
||
<p id="section-3.2-1">Registration is the only stage in OPAQUE that requires a server-authenticated
|
||
channel with confidentiality and integrity: either physical, out-of-band, PKI-based, etc.<a href="#section-3.2-1" class="pilcrow">¶</a></p>
|
||
<p id="section-3.2-2">The client inputs its credentials, which include its password and user
|
||
identifier, and the server inputs its parameters, which include its private key
|
||
and other information.<a href="#section-3.2-2" class="pilcrow">¶</a></p>
|
||
<p id="section-3.2-3">The client output of this stage is a single value <code>export_key</code> that the client
|
||
may use for application-specific purposes, e.g., as a symmetric key used to encrypt
|
||
additional information for storage on the server. The server does not have access to this
|
||
<code>export_key</code>.<a href="#section-3.2-3" class="pilcrow">¶</a></p>
|
||
<p id="section-3.2-4">The server output of this stage is a <code>record</code> corresponding to the client's
|
||
registration that it stores in a credential file alongside other clients
|
||
registrations as needed.<a href="#section-3.2-4" class="pilcrow">¶</a></p>
|
||
<p id="section-3.2-5">The registration flow is shown in <a href="#fig1" class="auto internal xref">Figure 1</a>, and the process is described in more detail in
|
||
<a href="#registration-phase" class="auto internal xref">Section 5</a>:<a href="#section-3.2-5" class="pilcrow">¶</a></p>
|
||
<div id="fig1">
|
||
<figure id="figure-1">
|
||
<div class="alignLeft art-text artwork" id="section-3.2-6.1">
|
||
<pre>
|
||
credentials parameters
|
||
| |
|
||
v v
|
||
Client Server
|
||
------------------------------------------------
|
||
registration request
|
||
------------------------->
|
||
registration response
|
||
<-------------------------
|
||
record
|
||
------------------------->
|
||
------------------------------------------------
|
||
| |
|
||
v v
|
||
export_key record
|
||
</pre>
|
||
</div>
|
||
<figcaption><a href="#figure-1" class="selfRef">Figure 1</a></figcaption></figure>
|
||
</div>
|
||
<p id="section-3.2-7">These messages are named <code>RegistrationRequest</code>, <code>RegistrationResponse</code>, and
|
||
<code>RegistrationRecord</code>, respectively. Their contents and wire format are defined in
|
||
<a href="#registration-messages" class="auto internal xref">Section 5.1</a>.<a href="#section-3.2-7" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="online-authenticated-key-exchange">
|
||
<section id="section-3.3">
|
||
<h3 id="name-online-authenticated-key-ex">
|
||
<a href="#section-3.3" class="section-number selfRef">3.3. </a><a href="#name-online-authenticated-key-ex" class="section-name selfRef">Online Authenticated Key Exchange</a>
|
||
</h3>
|
||
<p id="section-3.3-1">In this second stage, a client obtains credentials previously registered
|
||
with the server, recovers private key material using the password, and
|
||
subsequently uses them as input to the AKE protocol. As in the registration
|
||
phase, the client inputs its credentials, including its password and user
|
||
identifier, and the server inputs its parameters and the credential file <code>record</code>
|
||
corresponding to the client. The client outputs two values, an <code>export_key</code>
|
||
(matching that from registration) and a <code>session_key</code>, the latter of which
|
||
is the primary AKE protocol output. The server outputs a single value <code>session_key</code>
|
||
that matches that of the client. Upon completion, clients and servers can
|
||
use these values as needed.<a href="#section-3.3-1" class="pilcrow">¶</a></p>
|
||
<p id="section-3.3-2">The authenticated key exchange flow is shown in <a href="#fig2" class="auto internal xref">Figure 2</a>:<a href="#section-3.3-2" class="pilcrow">¶</a></p>
|
||
<div id="fig2">
|
||
<figure id="figure-2">
|
||
<div class="alignLeft art-text artwork" id="section-3.3-3.1">
|
||
<pre>
|
||
credentials (parameters, record)
|
||
| |
|
||
v v
|
||
Client Server
|
||
------------------------------------------------
|
||
AKE message 1
|
||
------------------------->
|
||
AKE message 2
|
||
<-------------------------
|
||
AKE message 3
|
||
------------------------->
|
||
------------------------------------------------
|
||
| |
|
||
v v
|
||
(export_key, session_key) session_key
|
||
</pre>
|
||
</div>
|
||
<figcaption><a href="#figure-2" class="selfRef">Figure 2</a></figcaption></figure>
|
||
</div>
|
||
<p id="section-3.3-4">These messages are named <code>KE1</code>, <code>KE2</code>, and <code>KE3</code>, respectively. They carry the
|
||
messages of the concurrent execution of the key recovery process (OPRF) and the
|
||
authenticated key exchange (AKE). Their corresponding wire formats are
|
||
specified in <a href="#ake-messages" class="auto internal xref">Section 6.1</a>.<a href="#section-3.3-4" class="pilcrow">¶</a></p>
|
||
<p id="section-3.3-5">The rest of this document describes the specifics of these stages in detail.
|
||
<a href="#client-material" class="auto internal xref">Section 4</a> describes how client credential information is
|
||
generated, encoded, and stored on the server during registration and recovered during
|
||
login. <a href="#registration-phase" class="auto internal xref">Section 5</a> describes the first registration stage of the protocol,
|
||
and <a href="#online-phase" class="auto internal xref">Section 6</a> describes the second authentication stage of the protocol.
|
||
<a href="#configurations" class="auto internal xref">Section 7</a> describes how to instantiate OPAQUE using different
|
||
cryptographic dependencies and parameters.<a href="#section-3.3-5" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="client-material">
|
||
<section id="section-4">
|
||
<h2 id="name-client-credential-storage-a">
|
||
<a href="#section-4" class="section-number selfRef">4. </a><a href="#name-client-credential-storage-a" class="section-name selfRef">Client Credential Storage and Key Recovery</a>
|
||
</h2>
|
||
<p id="section-4-1">OPAQUE makes use of a structure called <code>Envelope</code> to manage client credentials.
|
||
The client creates its <code>Envelope</code> on registration and sends it to the server for
|
||
storage. On every login, the server sends this <code>Envelope</code> to the client so it can
|
||
recover its key material for use in the AKE.<a href="#section-4-1" class="pilcrow">¶</a></p>
|
||
<p id="section-4-2">Applications may pin key material to identities if desired. If no identity is given
|
||
for a party, its value <span class="bcp14">MUST</span> default to its public key. The following types of
|
||
application credential information are considered:<a href="#section-4-2" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-4-3">
|
||
<dt id="section-4-3.1">
|
||
<code>client_private_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-4-3.2">The encoded client private key for the AKE protocol.<a href="#section-4-3.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-4-3.3">
|
||
<code>client_public_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-4-3.4">The encoded client public key for the AKE protocol.<a href="#section-4-3.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-4-3.5">
|
||
<code>server_public_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-4-3.6">The encoded server public key for the AKE protocol.<a href="#section-4-3.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-4-3.7">
|
||
<code>client_identity</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-4-3.8">The client identity. This is an
|
||
application-specific value, e.g., an email address or an account
|
||
name. If not specified, it defaults to the client's public key.<a href="#section-4-3.8" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-4-3.9">
|
||
<code>server_identity</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-4-3.10">The server identity. This is typically a domain
|
||
name, e.g., example.com. If not specified, it defaults to the
|
||
server's public key. See <a href="#identities" class="auto internal xref">Section 10.3</a> for information
|
||
about this identity.<a href="#section-4-3.10" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-4-4">A subset of these credential values are used in the <code>CleartextCredentials</code> structure as follows:<a href="#section-4-4" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-4-5">
|
||
<pre>
|
||
struct {
|
||
uint8 server_public_key[Npk];
|
||
uint8 server_identity<1..2^16-1>;
|
||
uint8 client_identity<1..2^16-1>;
|
||
} CleartextCredentials;
|
||
</pre><a href="#section-4-5" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-4-6">The function CreateCleartextCredentials constructs a <code>CleartextCredentials</code> structure given
|
||
application credential information.<a href="#section-4-6" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-4-7">
|
||
<pre>
|
||
CreateCleartextCredentials
|
||
|
||
Input:
|
||
- server_public_key, the encoded server public key
|
||
for the AKE protocol.
|
||
- client_public_key, the encoded client public key
|
||
for the AKE protocol.
|
||
- server_identity, the optional encoded server identity.
|
||
- client_identity, the optional encoded client identity.
|
||
|
||
Output:
|
||
- cleartext_credentials, a CleartextCredentials structure.
|
||
|
||
def CreateCleartextCredentials(server_public_key, client_public_key,
|
||
server_identity, client_identity):
|
||
# Set identities as public keys if no
|
||
# application-layer identity is provided
|
||
if server_identity == nil
|
||
server_identity = server_public_key
|
||
if client_identity == nil
|
||
client_identity = client_public_key
|
||
|
||
cleartext_credentials = CleartextCredentials {
|
||
server_public_key,
|
||
server_identity,
|
||
client_identity
|
||
}
|
||
|
||
return cleartext_credentials
|
||
</pre><a href="#section-4-7" class="pilcrow">¶</a>
|
||
</div>
|
||
<div id="key-recovery">
|
||
<section id="section-4.1">
|
||
<h3 id="name-key-recovery">
|
||
<a href="#section-4.1" class="section-number selfRef">4.1. </a><a href="#name-key-recovery" class="section-name selfRef">Key Recovery</a>
|
||
</h3>
|
||
<p id="section-4.1-1">This specification defines a key recovery mechanism that uses the stretched OPRF
|
||
output as a <code>seed</code> to directly derive the private and public keys using the
|
||
<code>DeriveDiffieHellmanKeyPair()</code> function defined in <a href="#key-creation" class="auto internal xref">Section 6.4.1</a>.<a href="#section-4.1-1" class="pilcrow">¶</a></p>
|
||
<div id="envelope-structure">
|
||
<section id="section-4.1.1">
|
||
<h4 id="name-envelope-structure">
|
||
<a href="#section-4.1.1" class="section-number selfRef">4.1.1. </a><a href="#name-envelope-structure" class="section-name selfRef">Envelope Structure</a>
|
||
</h4>
|
||
<p id="section-4.1.1-1">The key recovery mechanism defines its <code>Envelope</code> as follows:<a href="#section-4.1.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-4.1.1-2">
|
||
<pre>
|
||
struct {
|
||
uint8 envelope_nonce[Nn];
|
||
uint8 auth_tag[Nm];
|
||
} Envelope;
|
||
</pre><a href="#section-4.1.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-4.1.1-3">
|
||
<dt id="section-4.1.1-3.1">
|
||
<code>envelope_nonce</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-4.1.1-3.2">A randomly sampled nonce of length
|
||
<code>Nn</code> used to protect this <code>Envelope</code>.<a href="#section-4.1.1-3.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-4.1.1-3.3">
|
||
<code>auth_tag</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-4.1.1-3.4">An authentication tag protecting the
|
||
contents of the <code>Envelope</code>, covering <code>envelope_nonce</code> and
|
||
<code>CleartextCredentials</code>.<a href="#section-4.1.1-3.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="envelope-creation">
|
||
<section id="section-4.1.2">
|
||
<h4 id="name-envelope-creation">
|
||
<a href="#section-4.1.2" class="section-number selfRef">4.1.2. </a><a href="#name-envelope-creation" class="section-name selfRef">Envelope Creation</a>
|
||
</h4>
|
||
<p id="section-4.1.2-1">Clients create an <code>Envelope</code> at registration with the function <code>Store</code> defined
|
||
below. Note that <code>DeriveDiffieHellmanKeyPair</code> in this function can fail with negligible
|
||
probability. If this occurs, servers should re-run the function, sampling a
|
||
new <code>envelope_nonce</code>, to completion.<a href="#section-4.1.2-1" class="pilcrow">¶</a></p>
|
||
<div class="breakable sourcecode" id="section-4.1.2-2">
|
||
<pre>
|
||
Store
|
||
|
||
Input:
|
||
- randomized_password, a randomized password.
|
||
- server_public_key, the encoded server public key for
|
||
the AKE protocol.
|
||
- server_identity, the optional encoded server identity.
|
||
- client_identity, the optional encoded client identity.
|
||
|
||
Output:
|
||
- envelope, the client's Envelope structure.
|
||
- client_public_key, the client's AKE public key.
|
||
- masking_key, an encryption key used by the server with the
|
||
sole purpose of defending against client enumeration attacks.
|
||
- export_key, an additional client key.
|
||
|
||
def Store(randomized_password, server_public_key,
|
||
server_identity, client_identity):
|
||
envelope_nonce = random(Nn)
|
||
masking_key = Expand(randomized_password, "MaskingKey", Nh)
|
||
auth_key =
|
||
Expand(randomized_password, concat(envelope_nonce, "AuthKey"),
|
||
Nh)
|
||
export_key =
|
||
Expand(randomized_password, concat(envelope_nonce, "ExportKey"),
|
||
Nh)
|
||
seed =
|
||
Expand(randomized_password, concat(envelope_nonce, "PrivateKey"),
|
||
Nseed)
|
||
(_, client_public_key) = DeriveDiffieHellmanKeyPair(seed)
|
||
|
||
cleartext_credentials =
|
||
CreateCleartextCredentials(server_public_key, client_public_key,
|
||
server_identity, client_identity)
|
||
auth_tag =
|
||
MAC(auth_key, concat(
|
||
envelope_nonce,
|
||
server_public_key,
|
||
I2OSP(len(cleartext_credentials.server_identity), 2),
|
||
cleartext_credentials.server_identity,
|
||
I2OSP(len(cleartext_credentials.client_identity), 2),
|
||
cleartext_credentials.client_identity
|
||
))
|
||
|
||
envelope = Envelope {
|
||
envelope_nonce,
|
||
auth_tag
|
||
}
|
||
|
||
return (envelope, client_public_key, masking_key, export_key)
|
||
</pre><a href="#section-4.1.2-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="envelope-recovery">
|
||
<section id="section-4.1.3">
|
||
<h4 id="name-envelope-recovery">
|
||
<a href="#section-4.1.3" class="section-number selfRef">4.1.3. </a><a href="#name-envelope-recovery" class="section-name selfRef">Envelope Recovery</a>
|
||
</h4>
|
||
<p id="section-4.1.3-1">Clients recover their <code>Envelope</code> during login with the <code>Recover</code> function
|
||
defined below.<a href="#section-4.1.3-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-4.1.3-2">
|
||
<pre>
|
||
Recover
|
||
|
||
Input:
|
||
- randomized_password, a randomized password.
|
||
- server_public_key, the encoded server public key for the
|
||
AKE protocol.
|
||
- envelope, the client's Envelope structure.
|
||
- server_identity, the optional encoded server identity.
|
||
- client_identity, the optional encoded client identity.
|
||
|
||
Output:
|
||
- client_private_key, the encoded client private key for the
|
||
AKE protocol.
|
||
- cleartext_credentials, a CleartextCredentials structure.
|
||
- export_key, an additional client key.
|
||
|
||
Exceptions:
|
||
- EnvelopeRecoveryError, the Envelope fails to be recovered.
|
||
|
||
def Recover(randomized_password, server_public_key, envelope,
|
||
server_identity, client_identity):
|
||
auth_key =
|
||
Expand(randomized_password, concat(envelope.nonce, "AuthKey"),
|
||
Nh)
|
||
export_key =
|
||
Expand(randomized_password, concat(envelope.nonce, "ExportKey"),
|
||
Nh)
|
||
seed =
|
||
Expand(randomized_password, concat(envelope.nonce, "PrivateKey"),
|
||
Nseed)
|
||
(client_private_key, client_public_key) =
|
||
DeriveDiffieHellmanKeyPair(seed)
|
||
|
||
cleartext_credentials =
|
||
CreateCleartextCredentials(server_public_key, client_public_key,
|
||
server_identity, client_identity)
|
||
expected_tag =
|
||
MAC(auth_key, concat(envelope.nonce, cleartext_credentials))
|
||
If !ct_equal(envelope.auth_tag, expected_tag)
|
||
raise EnvelopeRecoveryError
|
||
return (client_private_key, cleartext_credentials, export_key)
|
||
</pre><a href="#section-4.1.3-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-4.1.3-3">In the case of <code>EnvelopeRecoveryError</code> being raised, all previously computed
|
||
intermediary values in this function <span class="bcp14">MUST</span> be deleted.<a href="#section-4.1.3-3" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="registration-phase">
|
||
<section id="section-5">
|
||
<h2 id="name-registration-2">
|
||
<a href="#section-5" class="section-number selfRef">5. </a><a href="#name-registration-2" class="section-name selfRef">Registration</a>
|
||
</h2>
|
||
<p id="section-5-1">The registration process proceeds as follows. The client inputs
|
||
the following values:<a href="#section-5-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-5-2">
|
||
<dt id="section-5-2.1">password:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5-2.2">The client's password.<a href="#section-5-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-5-2.3">creds:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5-2.4">The client credentials as described in <a href="#client-material" class="auto internal xref">Section 4</a>.<a href="#section-5-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-5-3">The server inputs the following values:<a href="#section-5-3" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-5-4">
|
||
<dt id="section-5-4.1">
|
||
<code>server_public_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5-4.2">The server public key for the AKE protocol.<a href="#section-5-4.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-5-4.3">
|
||
<code>credential_identifier</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5-4.4">A unique identifier for the client's
|
||
credential generated by the server.<a href="#section-5-4.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-5-4.5">
|
||
<code>client_identity</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5-4.6">The optional client identity as described in <a href="#client-material" class="auto internal xref">Section 4</a>.<a href="#section-5-4.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-5-4.7">
|
||
<code>oprf_seed</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5-4.8">A <code>seed</code> used to derive per-client OPRF keys.<a href="#section-5-4.8" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-5-5">The registration protocol then runs as shown below:<a href="#section-5-5" class="pilcrow">¶</a></p>
|
||
<div class="alignLeft art-text artwork" id="section-5-6">
|
||
<pre>
|
||
Client Server
|
||
------------------------------------------------------
|
||
(request, blind) = CreateRegistrationRequest(password)
|
||
|
||
request
|
||
------------------------->
|
||
|
||
response = CreateRegistrationResponse(request,
|
||
server_public_key,
|
||
credential_identifier,
|
||
oprf_seed)
|
||
|
||
response
|
||
<-------------------------
|
||
|
||
(record, export_key) = FinalizeRegistrationRequest(password,
|
||
blind,
|
||
response,
|
||
server_identity,
|
||
client_identity)
|
||
|
||
record
|
||
------------------------->
|
||
</pre><a href="#section-5-6" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-5-7"><a href="#registration-messages" class="auto internal xref">Section 5.1</a> describes the formats for the above messages, and
|
||
<a href="#registration-functions" class="auto internal xref">Section 5.2</a> describes details of the functions and the
|
||
corresponding parameters referenced above.<a href="#section-5-7" class="pilcrow">¶</a></p>
|
||
<p id="section-5-8">At the end of this interaction, the server stores the <code>record</code> object as the
|
||
credential file for each client along with the associated <code>credential_identifier</code>
|
||
and <code>client_identity</code> (if different). Note that the values <code>oprf_seed</code> and
|
||
<code>server_private_key</code> from the server's setup phase must also be persisted.
|
||
The <code>oprf_seed</code> value <span class="bcp14">SHOULD</span> be used for all clients; see <a href="#preventing-client-enumeration" class="auto internal xref">Section 10.9</a>
|
||
for the justification behind this, along with a description of the exception in which
|
||
applications may choose to avoid the use of a global <code>oprf_seed</code> value across clients
|
||
and instead sample OPRF keys uniquely for each client. The <code>server_private_key</code> may
|
||
be unique for each client.<a href="#section-5-8" class="pilcrow">¶</a></p>
|
||
<p id="section-5-9">Both client and server <span class="bcp14">MUST</span> validate the other party's public key before use.
|
||
See <a href="#validation" class="auto internal xref">Section 10.7</a> for more details. Upon completion, the server stores
|
||
the client's credentials for later use. Moreover, the client <span class="bcp14">MAY</span> use the output
|
||
<code>export_key</code> for further application-specific purposes; see <a href="#export-key-usage" class="auto internal xref">Section 10.4</a>.<a href="#section-5-9" class="pilcrow">¶</a></p>
|
||
<div id="registration-messages">
|
||
<section id="section-5.1">
|
||
<h3 id="name-registration-messages">
|
||
<a href="#section-5.1" class="section-number selfRef">5.1. </a><a href="#name-registration-messages" class="section-name selfRef">Registration Messages</a>
|
||
</h3>
|
||
<p id="section-5.1-1">This section contains definitions of the <code>RegistrationRequest</code>,
|
||
<code>RegistrationResponse</code>, and <code>RegistrationRecord</code> messages exchanged between
|
||
client and server during registration.<a href="#section-5.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-5.1-2">
|
||
<pre>
|
||
struct {
|
||
uint8 blinded_message[Noe];
|
||
} RegistrationRequest;
|
||
</pre><a href="#section-5.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-5.1-3">
|
||
<dt id="section-5.1-3.1">blinded_message:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5.1-3.2">A serialized OPRF group element.<a href="#section-5.1-3.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<div class="sourcecode" id="section-5.1-4">
|
||
<pre>
|
||
struct {
|
||
uint8 evaluated_message[Noe];
|
||
uint8 server_public_key[Npk];
|
||
} RegistrationResponse;
|
||
</pre><a href="#section-5.1-4" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-5.1-5">
|
||
<dt id="section-5.1-5.1">evaluated_message:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5.1-5.2">A serialized OPRF group element.<a href="#section-5.1-5.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-5.1-5.3">
|
||
<code>server_public_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5.1-5.4">The server's encoded public key that will be
|
||
used for the online AKE stage.<a href="#section-5.1-5.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<div class="sourcecode" id="section-5.1-6">
|
||
<pre>
|
||
struct {
|
||
uint8 client_public_key[Npk];
|
||
uint8 masking_key[Nh];
|
||
Envelope envelope;
|
||
} RegistrationRecord;
|
||
</pre><a href="#section-5.1-6" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-5.1-7">
|
||
<dt id="section-5.1-7.1">
|
||
<code>client_public_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5.1-7.2">The client's encoded public key
|
||
corresponding to the private key <code>client_private_key</code>.<a href="#section-5.1-7.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-5.1-7.3">
|
||
<code>masking_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5.1-7.4">An encryption key used by the server with
|
||
the sole purpose of defending against client enumeration
|
||
attacks.<a href="#section-5.1-7.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-5.1-7.5">envelope:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-5.1-7.6">The client's <code>Envelope</code> structure.<a href="#section-5.1-7.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="registration-functions">
|
||
<section id="section-5.2">
|
||
<h3 id="name-registration-functions">
|
||
<a href="#section-5.2" class="section-number selfRef">5.2. </a><a href="#name-registration-functions" class="section-name selfRef">Registration Functions</a>
|
||
</h3>
|
||
<p id="section-5.2-1">This section contains definitions of the functions used by client and server
|
||
during registration, including <code>CreateRegistrationRequest</code>, <code>CreateRegistrationResponse</code>,
|
||
and <code>FinalizeRegistrationRequest</code>.<a href="#section-5.2-1" class="pilcrow">¶</a></p>
|
||
<div id="createregistrationrequest">
|
||
<section id="section-5.2.1">
|
||
<h4 id="name-createregistrationrequest">
|
||
<a href="#section-5.2.1" class="section-number selfRef">5.2.1. </a><a href="#name-createregistrationrequest" class="section-name selfRef">CreateRegistrationRequest</a>
|
||
</h4>
|
||
<p id="section-5.2.1-1">To begin the registration flow, the client executes the following function. This function
|
||
can fail with an <code>InvalidInputError</code> error with negligible probability. A different input
|
||
password is necessary in the event of this error.<a href="#section-5.2.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-5.2.1-2">
|
||
<pre>
|
||
CreateRegistrationRequest
|
||
|
||
Input:
|
||
- password, an opaque byte string containing the client's password.
|
||
|
||
Output:
|
||
- request, a RegistrationRequest structure.
|
||
- blind, an OPRF scalar value.
|
||
|
||
Exceptions:
|
||
- InvalidInputError, when Blind fails
|
||
|
||
def CreateRegistrationRequest(password):
|
||
(blind, blinded_element) = Blind(password)
|
||
blinded_message = SerializeElement(blinded_element)
|
||
request = RegistrationRequest {
|
||
blinded_message
|
||
}
|
||
return (request, blind)
|
||
</pre><a href="#section-5.2.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="create-reg-response">
|
||
<section id="section-5.2.2">
|
||
<h4 id="name-createregistrationresponse">
|
||
<a href="#section-5.2.2" class="section-number selfRef">5.2.2. </a><a href="#name-createregistrationresponse" class="section-name selfRef">CreateRegistrationResponse</a>
|
||
</h4>
|
||
<p id="section-5.2.2-1">To process the client's registration request, the server executes
|
||
the following function. This function can fail with a <code>DeriveKeyPairError</code>
|
||
error with negligible probability. In this case, applications can
|
||
choose a new <code>credential_identifier</code> for this registration <code>record</code>
|
||
and rerun this function.<a href="#section-5.2.2-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-5.2.2-2">
|
||
<pre>
|
||
CreateRegistrationResponse
|
||
|
||
Input:
|
||
- request, a RegistrationRequest structure.
|
||
- server_public_key, the server's public key.
|
||
- credential_identifier, an identifier that uniquely represents
|
||
the credential.
|
||
- oprf_seed, the seed of Nh bytes used by the server to generate
|
||
an oprf_key.
|
||
|
||
Output:
|
||
- response, a RegistrationResponse structure.
|
||
|
||
Exceptions:
|
||
- DeserializeError, when OPRF element deserialization fails.
|
||
- DeriveKeyPairError, when OPRF key derivation fails.
|
||
|
||
def CreateRegistrationResponse(request, server_public_key,
|
||
credential_identifier, oprf_seed):
|
||
seed =
|
||
Expand(oprf_seed, concat(credential_identifier, "OprfKey"), Nok)
|
||
(oprf_key, _) = DeriveKeyPair(seed, "OPAQUE-DeriveKeyPair")
|
||
|
||
blinded_element = DeserializeElement(request.blinded_message)
|
||
evaluated_element = BlindEvaluate(oprf_key, blinded_element)
|
||
evaluated_message = SerializeElement(evaluated_element)
|
||
|
||
response = RegistrationResponse {
|
||
evaluated_message,
|
||
server_public_key
|
||
}
|
||
|
||
return response
|
||
</pre><a href="#section-5.2.2-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="finalize-request">
|
||
<section id="section-5.2.3">
|
||
<h4 id="name-finalizeregistrationrequest">
|
||
<a href="#section-5.2.3" class="section-number selfRef">5.2.3. </a><a href="#name-finalizeregistrationrequest" class="section-name selfRef">FinalizeRegistrationRequest</a>
|
||
</h4>
|
||
<p id="section-5.2.3-1">To create the user <code>record</code> used for subsequent authentication and complete the
|
||
registration flow, the client executes the following function.<a href="#section-5.2.3-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-5.2.3-2">
|
||
<pre>
|
||
FinalizeRegistrationRequest
|
||
|
||
Input:
|
||
- password, an opaque byte string containing the client's password.
|
||
- blind, an OPRF scalar value.
|
||
- response, a RegistrationResponse structure.
|
||
- server_identity, the optional encoded server identity.
|
||
- client_identity, the optional encoded client identity.
|
||
|
||
Output:
|
||
- record, a RegistrationRecord structure.
|
||
- export_key, an additional client key.
|
||
|
||
Exceptions:
|
||
- DeserializeError, when OPRF element deserialization fails.
|
||
|
||
def FinalizeRegistrationRequest(password, blind, response,
|
||
server_identity, client_identity):
|
||
evaluated_element = DeserializeElement(response.evaluated_message)
|
||
oprf_output = Finalize(password, blind, evaluated_element)
|
||
|
||
stretched_oprf_output = Stretch(oprf_output)
|
||
randomized_password =
|
||
Extract("", concat(oprf_output, stretched_oprf_output))
|
||
|
||
(envelope, client_public_key, masking_key, export_key) =
|
||
Store(randomized_password, response.server_public_key,
|
||
server_identity, client_identity)
|
||
|
||
record = RegistrationRecord {
|
||
client_public_key,
|
||
masking_key,
|
||
envelope
|
||
}
|
||
|
||
return (record, export_key)
|
||
</pre><a href="#section-5.2.3-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-5.2.3-3">See <a href="#online-phase" class="auto internal xref">Section 6</a> for details about the output <code>export_key</code> usage.<a href="#section-5.2.3-3" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="online-phase">
|
||
<section id="section-6">
|
||
<h2 id="name-online-authenticated-key-exc">
|
||
<a href="#section-6" class="section-number selfRef">6. </a><a href="#name-online-authenticated-key-exc" class="section-name selfRef">Online Authenticated Key Exchange</a>
|
||
</h2>
|
||
<p id="section-6-1">The generic outline of OPAQUE with a 3-message AKE protocol includes three
|
||
messages: <code>KE1</code>, <code>KE2</code>, and <code>KE3</code>. <code>KE1</code> and <code>KE2</code> include key exchange shares (e.g., DH
|
||
values) sent by the client and server, respectively. <code>KE3</code> provides explicit
|
||
client authentication and full forward security (without it, forward secrecy
|
||
is only achieved against eavesdroppers, which is insufficient for OPAQUE
|
||
security).<a href="#section-6-1" class="pilcrow">¶</a></p>
|
||
<p id="section-6-2">This section describes the online authenticated key exchange protocol flow,
|
||
message encoding, and helper functions. This stage is composed of a concurrent
|
||
OPRF and key exchange flow. The key exchange protocol is authenticated using the
|
||
client and server credentials established during registration; see <a href="#registration-phase" class="auto internal xref">Section 5</a>.
|
||
In the end, the client proves its knowledge of the password, and both client and
|
||
server agree on (1) a mutually authenticated shared secret key and (2) any optional
|
||
application information exchange during the handshake.<a href="#section-6-2" class="pilcrow">¶</a></p>
|
||
<p id="section-6-3">In this stage, the client inputs the following values:<a href="#section-6-3" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6-4">
|
||
<dt id="section-6-4.1">password:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-4.2">The client's password.<a href="#section-6-4.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-4.3">
|
||
<code>client_identity</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-4.4">The client identity as described in <a href="#client-material" class="auto internal xref">Section 4</a>.<a href="#section-6-4.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-6-5">The server inputs the following values:<a href="#section-6-5" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6-6">
|
||
<dt id="section-6-6.1">
|
||
<code>server_private_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-6.2">The server's private key for the AKE protocol.<a href="#section-6-6.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-6.3">
|
||
<code>server_public_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-6.4">The server's public key for the AKE protocol.<a href="#section-6-6.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-6.5">
|
||
<code>server_identity</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-6.6">The server identity as described in <a href="#client-material" class="auto internal xref">Section 4</a>.<a href="#section-6-6.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-6.7">
|
||
<code>record</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-6.8">The <code>RegistrationRecord</code> object corresponding to the client's registration.<a href="#section-6-6.8" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-6.9">
|
||
<code>credential_identifier</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-6.10">An identifier that uniquely represents the credential.<a href="#section-6-6.10" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-6.11">
|
||
<code>oprf_seed</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-6.12">The <code>seed</code> used to derive per-client OPRF keys.<a href="#section-6-6.12" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-6-7">The client receives two outputs: a session secret and an export key. The export
|
||
key is only available to the client and may be used for additional
|
||
application-specific purposes, as outlined in <a href="#export-key-usage" class="auto internal xref">Section 10.4</a>.
|
||
Clients <span class="bcp14">MUST NOT</span> use the output <code>export_key</code> before
|
||
authenticating the peer in the authenticated key exchange protocol.
|
||
See <a href="#alternate-key-recovery" class="auto internal xref">Appendix A</a> for more details about this
|
||
requirement. The server receives a single output: a session secret matching the
|
||
client's.<a href="#section-6-7" class="pilcrow">¶</a></p>
|
||
<p id="section-6-8">The protocol runs as shown below:<a href="#section-6-8" class="pilcrow">¶</a></p>
|
||
<div class="alignLeft art-text artwork" id="section-6-9">
|
||
<pre>
|
||
Client Server
|
||
------------------------------------------------------
|
||
ke1 = GenerateKE1(password)
|
||
|
||
ke1
|
||
------------------------->
|
||
|
||
ke2 = GenerateKE2(server_identity, server_private_key,
|
||
server_public_key, record,
|
||
credential_identifier, oprf_seed, ke1)
|
||
|
||
ke2
|
||
<-------------------------
|
||
|
||
(ke3,
|
||
session_key,
|
||
export_key) = GenerateKE3(client_identity,
|
||
server_identity, ke2)
|
||
|
||
ke3
|
||
------------------------->
|
||
|
||
session_key = ServerFinish(ke3)
|
||
</pre><a href="#section-6-9" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-6-10">Both client and server may use implicit internal state objects to keep necessary
|
||
material for the OPRF and AKE, <code>client_state</code>, and <code>server_state</code>, respectively.<a href="#section-6-10" class="pilcrow">¶</a></p>
|
||
<p id="section-6-11">The client state <code>ClientState</code> may have the following fields:<a href="#section-6-11" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6-12">
|
||
<dt id="section-6-12.1">password:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-12.2">The client's password.<a href="#section-6-12.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-12.3">
|
||
<code>blind</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-12.4">The random blinding inverter returned by <code>Blind()</code>.<a href="#section-6-12.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6-12.5">client_ake_state:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-12.6">The <code>ClientAkeState</code> as defined in <a href="#protocol-3dh" class="auto internal xref">Section 6.4</a>.<a href="#section-6-12.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-6-13">The server state <code>ServerState</code> may have the following fields:<a href="#section-6-13" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6-14">
|
||
<dt id="section-6-14.1">server_ake_state:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6-14.2">The <code>ServerAkeState</code> as defined in <a href="#protocol-3dh" class="auto internal xref">Section 6.4</a>.<a href="#section-6-14.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-6-15">Both of these states are ephemeral and should be erased after the protocol completes.<a href="#section-6-15" class="pilcrow">¶</a></p>
|
||
<p id="section-6-16">The rest of this section describes these authenticated key exchange messages
|
||
and their parameters in more detail. <a href="#ake-messages" class="auto internal xref">Section 6.1</a> defines the structure of the
|
||
messages passed between client and server in the above setup. <a href="#ake-functions" class="auto internal xref">Section 6.2</a>
|
||
describes details of the functions and corresponding parameters mentioned above.
|
||
<a href="#cred-retrieval" class="auto internal xref">Section 6.3</a> discusses internal functions used for retrieving client
|
||
credentials, and <a href="#protocol-3dh" class="auto internal xref">Section 6.4</a> discusses how these functions are used to execute
|
||
the authenticated key exchange protocol.<a href="#section-6-16" class="pilcrow">¶</a></p>
|
||
<div id="ake-messages">
|
||
<section id="section-6.1">
|
||
<h3 id="name-ake-messages">
|
||
<a href="#section-6.1" class="section-number selfRef">6.1. </a><a href="#name-ake-messages" class="section-name selfRef">AKE Messages</a>
|
||
</h3>
|
||
<p id="section-6.1-1">In this section, we define the <code>KE1</code>, <code>KE2</code>, and <code>KE3</code> structs that make up
|
||
the AKE messages used in the protocol. <code>KE1</code> is composed of a <code>CredentialRequest</code>
|
||
and <code>AuthRequest</code>, and <code>KE2</code> is composed of a <code>CredentialResponse</code>
|
||
and <code>AuthResponse</code>.<a href="#section-6.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.1-2">
|
||
<pre>
|
||
struct {
|
||
uint8 client_nonce[Nn];
|
||
uint8 client_public_keyshare[Npk];
|
||
} AuthRequest;
|
||
</pre><a href="#section-6.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.1-3">
|
||
<dt id="section-6.1-3.1">client_nonce:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-3.2">A fresh randomly generated nonce of length <code>Nn</code>.<a href="#section-6.1-3.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.1-3.3">client_public_keyshare:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-3.4">A serialized client ephemeral public key of fixed size <code>Npk</code>.<a href="#section-6.1-3.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<div class="sourcecode" id="section-6.1-4">
|
||
<pre>
|
||
struct {
|
||
CredentialRequest credential_request;
|
||
AuthRequest auth_request;
|
||
} KE1;
|
||
</pre><a href="#section-6.1-4" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.1-5">
|
||
<dt id="section-6.1-5.1">credential_request:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-5.2">A <code>CredentialRequest</code> structure.<a href="#section-6.1-5.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.1-5.3">auth_request:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-5.4">An <code>AuthRequest</code> structure.<a href="#section-6.1-5.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<div class="sourcecode" id="section-6.1-6">
|
||
<pre>
|
||
struct {
|
||
uint8 server_nonce[Nn];
|
||
uint8 server_public_keyshare[Npk];
|
||
uint8 server_mac[Nm];
|
||
} AuthResponse;
|
||
</pre><a href="#section-6.1-6" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.1-7">
|
||
<dt id="section-6.1-7.1">server_nonce:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-7.2">A fresh randomly generated nonce of length <code>Nn</code>.<a href="#section-6.1-7.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.1-7.3">
|
||
<code>server_public_key</code>share:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-7.4">A server ephemeral public key of
|
||
fixed size <code>Npk</code>, where <code>Npk</code> depends on the
|
||
corresponding prime order group.<a href="#section-6.1-7.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.1-7.5">server_mac:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-7.6">An authentication tag computed over the
|
||
handshake transcript computed using <code>Km2</code>, which is defined
|
||
below.<a href="#section-6.1-7.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<div class="sourcecode" id="section-6.1-8">
|
||
<pre>
|
||
struct {
|
||
CredentialResponse credential_response;
|
||
AuthResponse auth_response;
|
||
} KE2;
|
||
</pre><a href="#section-6.1-8" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.1-9">
|
||
<dt id="section-6.1-9.1">credential_response:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-9.2">A <code>CredentialResponse</code> structure.<a href="#section-6.1-9.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.1-9.3">auth_response:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-9.4">An <code>AuthResponse</code> structure.<a href="#section-6.1-9.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<div class="sourcecode" id="section-6.1-10">
|
||
<pre>
|
||
struct {
|
||
uint8 client_mac[Nm];
|
||
} KE3;
|
||
</pre><a href="#section-6.1-10" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.1-11">
|
||
<dt id="section-6.1-11.1">client_mac:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.1-11.2">An authentication tag computed over the
|
||
handshake transcript of fixed size <code>Nm</code>, computed using
|
||
<code>Km2</code>, defined below.<a href="#section-6.1-11.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="ake-functions">
|
||
<section id="section-6.2">
|
||
<h3 id="name-ake-functions">
|
||
<a href="#section-6.2" class="section-number selfRef">6.2. </a><a href="#name-ake-functions" class="section-name selfRef">AKE Functions</a>
|
||
</h3>
|
||
<p id="section-6.2-1">In this section, we define the main functions used to produce the AKE messages
|
||
in the protocol. Note that this section relies on definitions of subroutines defined
|
||
in later sections:<a href="#section-6.2-1" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-6.2-2.1">
|
||
<p id="section-6.2-2.1.1"><code>CreateCredentialRequest</code>, <code>CreateCredentialResponse</code>, and <code>RecoverCredentials</code> are defined in <a href="#cred-retrieval" class="auto internal xref">Section 6.3</a>.<a href="#section-6.2-2.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-6.2-2.2">
|
||
<p id="section-6.2-2.2.1"><code>AuthClientStart</code>, <code>AuthServerRespond</code>, <code>AuthClientFinalize</code>, and <code>AuthServerFinalize</code> are
|
||
defined in Sections <a href="#ake-client" class="auto internal xref">6.4.3</a> and <a href="#ake-server" class="auto internal xref">6.4.4</a>.<a href="#section-6.2-2.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
<div id="generateke1">
|
||
<section id="section-6.2.1">
|
||
<h4 id="name-generateke1">
|
||
<a href="#section-6.2.1" class="section-number selfRef">6.2.1. </a><a href="#name-generateke1" class="section-name selfRef">GenerateKE1</a>
|
||
</h4>
|
||
<p id="section-6.2.1-1">The <code>GenerateKE1</code> function begins the AKE protocol and produces the client's <code>KE1</code>
|
||
output for the server.<a href="#section-6.2.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.2.1-2">
|
||
<pre>
|
||
GenerateKE1
|
||
|
||
State:
|
||
- state, a ClientState structure.
|
||
|
||
Input:
|
||
- password, an opaque byte string containing the client's password.
|
||
|
||
Output:
|
||
- ke1, a KE1 message structure.
|
||
|
||
def GenerateKE1(password):
|
||
request, blind = CreateCredentialRequest(password)
|
||
state.password = password
|
||
state.blind = blind
|
||
ke1 = AuthClientStart(request)
|
||
return ke1
|
||
</pre><a href="#section-6.2.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="generateke2">
|
||
<section id="section-6.2.2">
|
||
<h4 id="name-generateke2">
|
||
<a href="#section-6.2.2" class="section-number selfRef">6.2.2. </a><a href="#name-generateke2" class="section-name selfRef">GenerateKE2</a>
|
||
</h4>
|
||
<p id="section-6.2.2-1">The <code>GenerateKE2</code> function continues the AKE protocol by processing the client's <code>KE1</code> message
|
||
and producing the server's <code>KE2</code> output.<a href="#section-6.2.2-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.2.2-2">
|
||
<pre>
|
||
GenerateKE2
|
||
|
||
State:
|
||
- state, a ServerState structure.
|
||
|
||
Input:
|
||
- server_identity, the optional encoded server identity, which is
|
||
set to server_public_key if not specified.
|
||
- server_private_key, the server's private key.
|
||
- server_public_key, the server's public key.
|
||
- record, the client's RegistrationRecord structure.
|
||
- credential_identifier, an identifier that uniquely represents
|
||
the credential.
|
||
- oprf_seed, the server-side seed of Nh bytes used to generate
|
||
an oprf_key.
|
||
- ke1, a KE1 message structure.
|
||
- client_identity, the optional encoded client identity, which is
|
||
set to client_public_key if not specified.
|
||
|
||
Output:
|
||
- ke2, a KE2 structure.
|
||
|
||
def GenerateKE2(server_identity, server_private_key,
|
||
server_public_key, record, credential_identifier,
|
||
oprf_seed, ke1, client_identity):
|
||
credential_response =
|
||
CreateCredentialResponse(ke1.credential_request,
|
||
server_public_key, record,
|
||
credential_identifier, oprf_seed)
|
||
cleartext_credentials =
|
||
CreateCleartextCredentials(server_public_key,
|
||
record.client_public_key,
|
||
server_identity, client_identity)
|
||
auth_response =
|
||
AuthServerRespond(cleartext_credentials, server_private_key,
|
||
record.client_public_key, ke1,
|
||
credential_response)
|
||
|
||
ke2 = KE2 {
|
||
credential_response,
|
||
auth_response
|
||
}
|
||
|
||
return ke2
|
||
</pre><a href="#section-6.2.2-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="generateke3">
|
||
<section id="section-6.2.3">
|
||
<h4 id="name-generateke3">
|
||
<a href="#section-6.2.3" class="section-number selfRef">6.2.3. </a><a href="#name-generateke3" class="section-name selfRef">GenerateKE3</a>
|
||
</h4>
|
||
<p id="section-6.2.3-1">The <code>GenerateKE3</code> function completes the AKE protocol for the client and
|
||
produces the client's <code>KE3</code> output for the server, as well as the <code>session_key</code>
|
||
and <code>export_key</code> outputs from the AKE.<a href="#section-6.2.3-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.2.3-2">
|
||
<pre>
|
||
GenerateKE3
|
||
|
||
State:
|
||
- state, a ClientState structure.
|
||
|
||
Input:
|
||
- client_identity, the optional encoded client identity, which is
|
||
set to client_public_key if not specified.
|
||
- server_identity, the optional encoded server identity, which is
|
||
set to server_public_key if not specified.
|
||
- ke2, a KE2 message structure.
|
||
|
||
Output:
|
||
- ke3, a KE3 message structure.
|
||
- session_key, the session's shared secret.
|
||
- export_key, an additional client key.
|
||
|
||
def GenerateKE3(client_identity, server_identity, ke2):
|
||
(client_private_key, cleartext_credentials, export_key) =
|
||
RecoverCredentials(state.password, state.blind,
|
||
ke2.credential_response,
|
||
server_identity, client_identity)
|
||
(ke3, session_key) =
|
||
AuthClientFinalize(cleartext_credentials,
|
||
client_private_key, ke2)
|
||
return (ke3, session_key, export_key)
|
||
</pre><a href="#section-6.2.3-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="serverfinish">
|
||
<section id="section-6.2.4">
|
||
<h4 id="name-serverfinish">
|
||
<a href="#section-6.2.4" class="section-number selfRef">6.2.4. </a><a href="#name-serverfinish" class="section-name selfRef">ServerFinish</a>
|
||
</h4>
|
||
<p id="section-6.2.4-1">The <code>ServerFinish</code> function completes the AKE protocol for the server, yielding the <code>session_key</code>.
|
||
|
||
Since the OPRF is a two-message protocol, <code>KE3</code> has no element of the OPRF. Therefore, <code>KE3</code>
|
||
invokes the AKE's <code>AuthServerFinalize</code> directly. The <code>AuthServerFinalize</code> function
|
||
takes <code>KE3</code> as input and <span class="bcp14">MUST</span> verify the client authentication material it contains
|
||
before the <code>session_key</code> value can be used. This verification is necessary to ensure
|
||
forward secrecy against active attackers.<a href="#section-6.2.4-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.2.4-2">
|
||
<pre>
|
||
ServerFinish
|
||
|
||
State:
|
||
- state, a ServerState structure.
|
||
|
||
Input:
|
||
- ke3, a KE3 structure.
|
||
|
||
Output:
|
||
- session_key, the shared session secret if and only if ke3 is valid.
|
||
|
||
def ServerFinish(ke3):
|
||
return AuthServerFinalize(ke3)
|
||
</pre><a href="#section-6.2.4-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-6.2.4-3">This function <span class="bcp14">MUST NOT</span> return the <code>session_key</code> value if the client authentication
|
||
material is invalid and may instead return an appropriate error message, such as
|
||
<code>ClientAuthenticationError</code>, which is invoked from <code>AuthServerFinalize</code>.<a href="#section-6.2.4-3" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="cred-retrieval">
|
||
<section id="section-6.3">
|
||
<h3 id="name-credential-retrieval">
|
||
<a href="#section-6.3" class="section-number selfRef">6.3. </a><a href="#name-credential-retrieval" class="section-name selfRef">Credential Retrieval</a>
|
||
</h3>
|
||
<p id="section-6.3-1">This section describes the sub-protocol run during authentication to retrieve and
|
||
recover the client credentials.<a href="#section-6.3-1" class="pilcrow">¶</a></p>
|
||
<div id="credential-retrieval-messages">
|
||
<section id="section-6.3.1">
|
||
<h4 id="name-credential-retrieval-messag">
|
||
<a href="#section-6.3.1" class="section-number selfRef">6.3.1. </a><a href="#name-credential-retrieval-messag" class="section-name selfRef">Credential Retrieval Messages</a>
|
||
</h4>
|
||
<p id="section-6.3.1-1">This section describes the <code>CredentialRequest</code> and <code>CredentialResponse</code> messages exchanged
|
||
between client and server to perform credential retrieval.<a href="#section-6.3.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.3.1-2">
|
||
<pre>
|
||
struct {
|
||
uint8 blinded_message[Noe];
|
||
} CredentialRequest;
|
||
</pre><a href="#section-6.3.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.3.1-3">
|
||
<dt id="section-6.3.1-3.1">blinded_message:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.3.1-3.2">A serialized OPRF group element.<a href="#section-6.3.1-3.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<div class="sourcecode" id="section-6.3.1-4">
|
||
<pre>
|
||
struct {
|
||
uint8 evaluated_message[Noe];
|
||
uint8 masking_nonce[Nn];
|
||
uint8 masked_response[Npk + Nn + Nm];
|
||
} CredentialResponse;
|
||
</pre><a href="#section-6.3.1-4" class="pilcrow">¶</a>
|
||
</div>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.3.1-5">
|
||
<dt id="section-6.3.1-5.1">evaluated_message:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.3.1-5.2">A serialized OPRF group element.<a href="#section-6.3.1-5.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.3.1-5.3">masking_nonce:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.3.1-5.4">A nonce used for the confidentiality of
|
||
the <code>masked_response</code> field.<a href="#section-6.3.1-5.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.3.1-5.5">
|
||
<code>masked_response</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.3.1-5.6">An encrypted form of the server's
|
||
public key and the client's <code>Envelope</code> structure.<a href="#section-6.3.1-5.6" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="credential-retrieval-functions">
|
||
<section id="section-6.3.2">
|
||
<h4 id="name-credential-retrieval-functi">
|
||
<a href="#section-6.3.2" class="section-number selfRef">6.3.2. </a><a href="#name-credential-retrieval-functi" class="section-name selfRef">Credential Retrieval Functions</a>
|
||
</h4>
|
||
<p id="section-6.3.2-1">This section describes the <code>CreateCredentialRequest</code>, <code>CreateCredentialResponse</code>,
|
||
and <code>RecoverCredentials</code> functions used for credential retrieval.<a href="#section-6.3.2-1" class="pilcrow">¶</a></p>
|
||
<div id="create-credential-request">
|
||
<section id="section-6.3.2.1">
|
||
<h5 id="name-createcredentialrequest">
|
||
<a href="#section-6.3.2.1" class="section-number selfRef">6.3.2.1. </a><a href="#name-createcredentialrequest" class="section-name selfRef">CreateCredentialRequest</a>
|
||
</h5>
|
||
<p id="section-6.3.2.1-1">The <code>CreateCredentialRequest</code> is used by the client to initiate the credential
|
||
retrieval process, and it produces a <code>CredentialRequest</code> message and OPRF state.
|
||
Like <code>CreateRegistrationRequest</code>, this function can fail with an <code>InvalidInputError</code>
|
||
error with negligible probability. However, this should not occur since
|
||
registration (via <code>CreateRegistrationRequest</code>) will fail when provided the same
|
||
password input.<a href="#section-6.3.2.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.3.2.1-2">
|
||
<pre>
|
||
CreateCredentialRequest
|
||
|
||
Input:
|
||
- password, an opaque byte string containing the client's password.
|
||
|
||
Output:
|
||
- request, a CredentialRequest structure.
|
||
- blind, an OPRF scalar value.
|
||
|
||
Exceptions:
|
||
- InvalidInputError, when Blind fails
|
||
|
||
def CreateCredentialRequest(password):
|
||
(blind, blinded_element) = Blind(password)
|
||
blinded_message = SerializeElement(blinded_element)
|
||
request = CredentialRequest {
|
||
blinded_message
|
||
}
|
||
return (request, blind)
|
||
</pre><a href="#section-6.3.2.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="create-credential-response">
|
||
<section id="section-6.3.2.2">
|
||
<h5 id="name-createcredentialresponse">
|
||
<a href="#section-6.3.2.2" class="section-number selfRef">6.3.2.2. </a><a href="#name-createcredentialresponse" class="section-name selfRef">CreateCredentialResponse</a>
|
||
</h5>
|
||
<p id="section-6.3.2.2-1">The <code>CreateCredentialResponse</code> function is used by the server to process the client's
|
||
<code>CredentialRequest</code> message and complete the credential retrieval process, producing
|
||
a <code>CredentialResponse</code>.<a href="#section-6.3.2.2-1" class="pilcrow">¶</a></p>
|
||
<p id="section-6.3.2.2-2">There are two scenarios to handle for the construction of a <code>CredentialResponse</code>
|
||
object: either the <code>record</code> for the client exists (corresponding to a properly
|
||
registered client) or it was never created (corresponding to an unregistered
|
||
client identity, possibly the result of an enumeration attack attempt).<a href="#section-6.3.2.2-2" class="pilcrow">¶</a></p>
|
||
<p id="section-6.3.2.2-3">In the case of an existing <code>record</code> with the corresponding identifier
|
||
<code>credential_identifier</code>, the server invokes the following function to
|
||
produce a <code>CredentialResponse</code>:<a href="#section-6.3.2.2-3" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.3.2.2-4">
|
||
<pre>
|
||
CreateCredentialResponse
|
||
|
||
Input:
|
||
- request, a CredentialRequest structure.
|
||
- server_public_key, the public key of the server.
|
||
- record, an instance of RegistrationRecord which is the server's
|
||
output from registration.
|
||
- credential_identifier, an identifier that uniquely represents
|
||
the credential.
|
||
- oprf_seed, the server-side seed of Nh bytes used to generate
|
||
an oprf_key.
|
||
|
||
Output:
|
||
- response, a CredentialResponse structure.
|
||
|
||
Exceptions:
|
||
- DeserializeError, when OPRF element deserialization fails.
|
||
|
||
def CreateCredentialResponse(request, server_public_key, record,
|
||
credential_identifier, oprf_seed):
|
||
seed =
|
||
Expand(oprf_seed, concat(credential_identifier, "OprfKey"), Nok)
|
||
(oprf_key, _) = DeriveKeyPair(seed, "OPAQUE-DeriveKeyPair")
|
||
|
||
blinded_element = DeserializeElement(request.blinded_message)
|
||
evaluated_element = BlindEvaluate(oprf_key, blinded_element)
|
||
evaluated_message = SerializeElement(evaluated_element)
|
||
|
||
masking_nonce = random(Nn)
|
||
credential_response_pad = Expand(record.masking_key,
|
||
concat(masking_nonce,
|
||
"CredentialResponsePad"),
|
||
Npk + Nn + Nm)
|
||
masked_response = xor(credential_response_pad,
|
||
concat(server_public_key, record.envelope))
|
||
|
||
response = CredentialResponse {
|
||
evaluated_message,
|
||
masking_nonce,
|
||
masked_response
|
||
}
|
||
|
||
return response
|
||
</pre><a href="#section-6.3.2.2-4" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-6.3.2.2-5">In the case of a <code>record</code> that does not exist and if client enumeration prevention is desired,
|
||
the server <span class="bcp14">MUST</span> respond to the credential request to fake the existence of the <code>record</code>.
|
||
The server <span class="bcp14">SHOULD</span> invoke the <code>CreateCredentialResponse</code> function with a fake client <code>record</code>
|
||
argument that is configured so that:<a href="#section-6.3.2.2-5" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-6.3.2.2-6.1">
|
||
<p id="section-6.3.2.2-6.1.1"><code>record.client_public_key</code> is set to a randomly generated public key of length <code>Npk</code><a href="#section-6.3.2.2-6.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-6.3.2.2-6.2">
|
||
<p id="section-6.3.2.2-6.2.1"><code>record.masking_key</code> is set to a random byte string of length <code>Nh</code><a href="#section-6.3.2.2-6.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-6.3.2.2-6.3">
|
||
<p id="section-6.3.2.2-6.3.1"><code>record.envelope</code> is set to the byte string consisting only of zeros of length <code>Nn + Nm</code><a href="#section-6.3.2.2-6.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
<p id="section-6.3.2.2-7">It is <span class="bcp14">RECOMMENDED</span> that a fake client <code>record</code> is created once (e.g., as the first user <code>record</code>
|
||
of the application) and then stored alongside legitimate client <code>records</code> to serve
|
||
subsequent client requests. This allows servers to retrieve the <code>record</code> in a time comparable
|
||
to that of a legitimate client <code>record</code>.<a href="#section-6.3.2.2-7" class="pilcrow">¶</a></p>
|
||
<p id="section-6.3.2.2-8">Note that the responses output by either scenario are indistinguishable to an adversary
|
||
that is unable to guess the registered password for the client corresponding to <code>credential_identifier</code>.<a href="#section-6.3.2.2-8" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="recover-credentials">
|
||
<section id="section-6.3.2.3">
|
||
<h5 id="name-recovercredentials">
|
||
<a href="#section-6.3.2.3" class="section-number selfRef">6.3.2.3. </a><a href="#name-recovercredentials" class="section-name selfRef">RecoverCredentials</a>
|
||
</h5>
|
||
<p id="section-6.3.2.3-1">The <code>RecoverCredentials</code> function is used by the client to process the server's
|
||
<code>CredentialResponse</code> message and produce the client's private key, server public
|
||
key, and the <code>export_key</code>.<a href="#section-6.3.2.3-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.3.2.3-2">
|
||
<pre>
|
||
RecoverCredentials
|
||
|
||
Input:
|
||
- password, an opaque byte string containing the client's password.
|
||
- blind, an OPRF scalar value.
|
||
- response, a CredentialResponse structure.
|
||
- server_identity, The optional encoded server identity.
|
||
- client_identity, The encoded client identity.
|
||
|
||
Output:
|
||
- client_private_key, the encoded client private key for
|
||
the AKE protocol.
|
||
- cleartext_credentials, a CleartextCredentials structure.
|
||
- export_key, an additional client key.
|
||
|
||
Exceptions:
|
||
- DeserializeError, when OPRF element deserialization fails.
|
||
|
||
def RecoverCredentials(password, blind, response,
|
||
server_identity, client_identity):
|
||
evaluated_element = DeserializeElement(response.evaluated_message)
|
||
|
||
oprf_output = Finalize(password, blind, evaluated_element)
|
||
stretched_oprf_output = Stretch(oprf_output)
|
||
|
||
randomized_password =
|
||
Extract("", concat(oprf_output, stretched_oprf_output))
|
||
|
||
masking_key = Expand(randomized_password, "MaskingKey", Nh)
|
||
|
||
credential_response_pad =
|
||
Expand(masking_key,
|
||
concat(response.masking_nonce, "CredentialResponsePad"),
|
||
Npk + Nn + Nm)
|
||
|
||
concat(server_public_key, envelope) =
|
||
xor(credential_response_pad, response.masked_response)
|
||
|
||
(client_private_key, cleartext_credentials, export_key) =
|
||
Recover(randomized_password, server_public_key, envelope,
|
||
server_identity, client_identity)
|
||
|
||
return (client_private_key, cleartext_credentials, export_key)
|
||
</pre><a href="#section-6.3.2.3-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="protocol-3dh">
|
||
<section id="section-6.4">
|
||
<h3 id="name-3dh-protocol">
|
||
<a href="#section-6.4" class="section-number selfRef">6.4. </a><a href="#name-3dh-protocol" class="section-name selfRef">3DH Protocol</a>
|
||
</h3>
|
||
<p id="section-6.4-1">This section describes the authenticated key exchange protocol for OPAQUE using
|
||
3DH, a 3-message AKE that satisfies the forward secrecy and KCI properties
|
||
discussed in <a href="#security-considerations" class="auto internal xref">Section 10</a>.<a href="#section-6.4-1" class="pilcrow">¶</a></p>
|
||
<p id="section-6.4-2">The client AKE state <code>ClientAkeState</code> mentioned in <a href="#online-phase" class="auto internal xref">Section 6</a> has the
|
||
following fields:<a href="#section-6.4-2" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.4-3">
|
||
<dt id="section-6.4-3.1">client_secret:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4-3.2">An opaque byte string of length <code>Nsk</code>.<a href="#section-6.4-3.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.4-3.3">ke1:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4-3.4">A value of type <code>KE1</code>.<a href="#section-6.4-3.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-6.4-4">The server AKE state <code>ServerAkeState</code> mentioned in <a href="#online-phase" class="auto internal xref">Section 6</a> has the
|
||
following fields:<a href="#section-6.4-4" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.4-5">
|
||
<dt id="section-6.4-5.1">expected_client_mac:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4-5.2">An opaque byte string of length <code>Nm</code>.<a href="#section-6.4-5.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.4-5.3">
|
||
<code>session_key</code>:</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4-5.4">An opaque byte string of length <code>Nx</code>.<a href="#section-6.4-5.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-6.4-6">Sections <a href="#ake-client" class="auto internal xref">6.4.3</a> and <a href="#ake-server" class="auto internal xref">6.4.4</a> specify the inner workings of client and
|
||
server functions, respectively.<a href="#section-6.4-6" class="pilcrow">¶</a></p>
|
||
<div id="key-creation">
|
||
<section id="section-6.4.1">
|
||
<h4 id="name-3dh-key-exchange-functions">
|
||
<a href="#section-6.4.1" class="section-number selfRef">6.4.1. </a><a href="#name-3dh-key-exchange-functions" class="section-name selfRef">3DH Key Exchange Functions</a>
|
||
</h4>
|
||
<p id="section-6.4.1-1">We assume the following functions exist for all Diffie-Hellman key exchange
|
||
variants:<a href="#section-6.4.1-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.4.1-2">
|
||
<dt id="section-6.4.1-2.1">DeriveDiffieHellmanKeyPair(seed):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1-2.2">Derive a private and
|
||
public Diffie-Hellman key pair deterministically from the input
|
||
<code>seed</code>. The type of the private key depends on the
|
||
implementation, whereas the type of the public key is a byte
|
||
string of <code>Npk</code> bytes.<a href="#section-6.4.1-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.4.1-2.3">DiffieHellman(k, B):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1-2.4">A function that performs the
|
||
Diffie-Hellman operation between the private input <code>k</code> and
|
||
public input <code>B</code>. The output of this function is a unique,
|
||
fixed-length byte string.<a href="#section-6.4.1-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
<p id="section-6.4.1-3">It is <span class="bcp14">RECOMMENDED</span> to use Elliptic Curve Diffie-Hellman for this key exchange protocol.
|
||
Implementations for recommended groups in <a href="#configurations" class="auto internal xref">Section 7</a>, as well as groups
|
||
covered by test vectors in <a href="#test-vectors" class="auto internal xref">Appendix C</a>, are described in the following sections.<a href="#section-6.4.1-3" class="pilcrow">¶</a></p>
|
||
<div id="dh-ristretto255">
|
||
<section id="section-6.4.1.1">
|
||
<h5 id="name-3dh-ristretto255">
|
||
<a href="#section-6.4.1.1" class="section-number selfRef">6.4.1.1. </a><a href="#name-3dh-ristretto255" class="section-name selfRef">3DH ristretto255</a>
|
||
</h5>
|
||
<p id="section-6.4.1.1-1">This section describes the implementation of the Diffie-Hellman key exchange functions based on ristretto255
|
||
as defined in <span>[<a href="#RFC9496" class="cite xref">RFC9496</a>]</span>.<a href="#section-6.4.1.1-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.4.1.1-2">
|
||
<dt id="section-6.4.1.1-2.1">DeriveDiffieHellmanKeyPair(seed):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1.1-2.2">This function is
|
||
implemented as DeriveKeyPair(seed,
|
||
"OPAQUE-DeriveDiffieHellmanKeyPair"), where DeriveKeyPair is as
|
||
specified in <span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.2" class="relref">Section 3.2</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>. The public
|
||
value from DeriveKeyPair is encoded using SerializeElement from
|
||
<span><a href="https://rfc-editor.org/rfc/rfc9497#section-2.1" class="relref">Section 2.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>.<a href="#section-6.4.1.1-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.4.1.1-2.3">DiffieHellman(k, B):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1.1-2.4">Implemented as scalar
|
||
multiplication as described in <span>[<a href="#RFC9496" class="cite xref">RFC9496</a>]</span> after decoding
|
||
<code>B</code> from its encoded input using the Decode function in
|
||
<span><a href="https://rfc-editor.org/rfc/rfc9496#section-4.3.1" class="relref">Section 4.3.1</a> of [<a href="#RFC9496" class="cite xref">RFC9496</a>]</span>. The output is
|
||
then encoded using the SerializeElement function of the OPRF
|
||
group described in <span><a href="https://rfc-editor.org/rfc/rfc9497#section-2.1" class="relref">Section 2.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>.<a href="#section-6.4.1.1-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="dh-p-256">
|
||
<section id="section-6.4.1.2">
|
||
<h5 id="name-3dh-p-256">
|
||
<a href="#section-6.4.1.2" class="section-number selfRef">6.4.1.2. </a><a href="#name-3dh-p-256" class="section-name selfRef">3DH P-256</a>
|
||
</h5>
|
||
<p id="section-6.4.1.2-1">This section describes the implementation of the Diffie-Hellman key exchange functions based on NIST P-256
|
||
as defined in <span>[<a href="#NISTCurves" class="cite xref">NISTCurves</a>]</span>.<a href="#section-6.4.1.2-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.4.1.2-2">
|
||
<dt id="section-6.4.1.2-2.1">DeriveDiffieHellmanKeyPair(seed):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1.2-2.2">As defined in
|
||
<a href="#dh-ristretto255" class="auto internal xref">Section 6.4.1.1</a>.<a href="#section-6.4.1.2-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.4.1.2-2.3">DiffieHellman(k, B):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1.2-2.4">Implemented as
|
||
scalar multiplication as described in <span>[<a href="#NISTCurves" class="cite xref">NISTCurves</a>]</span> after decoding <code>B</code>
|
||
from its encoded input using the compressed
|
||
Octet-String-to-Elliptic-Curve-Point method
|
||
according to <span>[<a href="#NISTCurves" class="cite xref">NISTCurves</a>]</span>. The
|
||
output is then encoded using the SerializeElement
|
||
function of the OPRF group described in <span><a href="https://rfc-editor.org/rfc/rfc9497#section-2.1" class="relref">Section 2.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>.<a href="#section-6.4.1.2-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="dh-curve25519">
|
||
<section id="section-6.4.1.3">
|
||
<h5 id="name-3dh-curve25519">
|
||
<a href="#section-6.4.1.3" class="section-number selfRef">6.4.1.3. </a><a href="#name-3dh-curve25519" class="section-name selfRef">3DH Curve25519</a>
|
||
</h5>
|
||
<p id="section-6.4.1.3-1">This section describes the implementation of the Diffie-Hellman key exchange functions based on Curve25519
|
||
as defined in <span>[<a href="#RFC7748" class="cite xref">RFC7748</a>]</span>.<a href="#section-6.4.1.3-1" class="pilcrow">¶</a></p>
|
||
<span class="break"></span><dl class="dlParallel" id="section-6.4.1.3-2">
|
||
<dt id="section-6.4.1.3-2.1">DeriveDiffieHellmanKeyPair(seed):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1.3-2.2">This function is
|
||
implemented by returning the private key <code>k</code> based on
|
||
<code>seed</code> (of length <code>Nseed = 32</code> bytes) as described in
|
||
<span><a href="https://rfc-editor.org/rfc/rfc7748#section-5" class="relref">Section 5</a> of [<a href="#RFC7748" class="cite xref">RFC7748</a>]</span>, as well as the result of
|
||
DiffieHellman(k, B), where B is the base point of
|
||
Curve25519.<a href="#section-6.4.1.3-2.2" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
<dt id="section-6.4.1.3-2.3">DiffieHellman(k, B):</dt>
|
||
<dd style="margin-left: 1.5em" id="section-6.4.1.3-2.4">Implemented using the X25519
|
||
function in <span><a href="https://rfc-editor.org/rfc/rfc7748#section-5" class="relref">Section 5</a> of [<a href="#RFC7748" class="cite xref">RFC7748</a>]</span>. The output
|
||
is then used raw with no processing.<a href="#section-6.4.1.3-2.4" class="pilcrow">¶</a>
|
||
</dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="key-schedule-functions">
|
||
<section id="section-6.4.2">
|
||
<h4 id="name-key-schedule-functions">
|
||
<a href="#section-6.4.2" class="section-number selfRef">6.4.2. </a><a href="#name-key-schedule-functions" class="section-name selfRef">Key Schedule Functions</a>
|
||
</h4>
|
||
<p id="section-6.4.2-1">This section contains functions used for the AKE key schedule.<a href="#section-6.4.2-1" class="pilcrow">¶</a></p>
|
||
<div id="transcript-functions">
|
||
<section id="section-6.4.2.1">
|
||
<h5 id="name-transcript-functions">
|
||
<a href="#section-6.4.2.1" class="section-number selfRef">6.4.2.1. </a><a href="#name-transcript-functions" class="section-name selfRef">Transcript Functions</a>
|
||
</h5>
|
||
<p id="section-6.4.2.1-1">The OPAQUE-3DH key derivation procedures make use of the functions below that are repurposed from TLS 1.3 <span>[<a href="#RFC8446" class="cite xref">RFC8446</a>]</span>.<a href="#section-6.4.2.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.4.2.1-2">
|
||
<pre>
|
||
Expand-Label(Secret, Label, Context, Length) =
|
||
Expand(Secret, CustomLabel, Length)
|
||
</pre><a href="#section-6.4.2.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-6.4.2.1-3">Where CustomLabel is specified and encoded (following <span><a href="https://rfc-editor.org/rfc/rfc8446#section-3.4" class="relref">Section 3.4</a> of [<a href="#RFC8446" class="cite xref">RFC8446</a>]</span>) as:<a href="#section-6.4.2.1-3" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.4.2.1-4">
|
||
<pre>
|
||
struct {
|
||
uint16 length = Length;
|
||
opaque label<8..255> = "OPAQUE-" + Label;
|
||
uint8 context<0..255> = Context;
|
||
} CustomLabel;
|
||
|
||
Derive-Secret(Secret, Label, Transcript-Hash) =
|
||
Expand-Label(Secret, Label, Transcript-Hash, Nx)
|
||
</pre><a href="#section-6.4.2.1-4" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-6.4.2.1-5">Note that the <code>Label</code> parameter is not a NULL-terminated string.<a href="#section-6.4.2.1-5" class="pilcrow">¶</a></p>
|
||
<p id="section-6.4.2.1-6">OPAQUE-3DH can optionally include application-specific, shared <code>context</code> information in the
|
||
transcript, such as configuration parameters or application-specific information, e.g.,
|
||
"appXYZ-v1.2.3".<a href="#section-6.4.2.1-6" class="pilcrow">¶</a></p>
|
||
<p id="section-6.4.2.1-7">The OPAQUE-3DH key schedule requires a <code>preamble</code>, which is computed as follows.<a href="#section-6.4.2.1-7" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.4.2.1-8">
|
||
<pre>
|
||
Preamble
|
||
|
||
Parameters:
|
||
- context, optional shared context information.
|
||
|
||
Input:
|
||
- client_identity, the optional encoded client identity, which is set
|
||
to client_public_key if not specified.
|
||
- ke1, a KE1 message structure.
|
||
- server_identity, the optional encoded server identity, which is set
|
||
to server_public_key if not specified.
|
||
- credential_response, the corresponding field on the KE2 structure.
|
||
- server_nonce, the corresponding field on the AuthResponse
|
||
structure.
|
||
- server_public_keyshare, the corresponding field on the AuthResponse
|
||
structure.
|
||
|
||
Output:
|
||
- preamble, the protocol transcript with identities and messages.
|
||
|
||
def Preamble(client_identity, ke1, server_identity,
|
||
credential_response, server_nonce,
|
||
server_public_keyshare):
|
||
preamble = concat("OPAQUEv1-",
|
||
I2OSP(len(context), 2), context,
|
||
I2OSP(len(client_identity), 2), client_identity,
|
||
ke1,
|
||
I2OSP(len(server_identity), 2), server_identity,
|
||
credential_response,
|
||
server_nonce,
|
||
server_public_keyshare)
|
||
return preamble
|
||
</pre><a href="#section-6.4.2.1-8" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="shared-secret-derivation">
|
||
<section id="section-6.4.2.2">
|
||
<h5 id="name-shared-secret-derivation">
|
||
<a href="#section-6.4.2.2" class="section-number selfRef">6.4.2.2. </a><a href="#name-shared-secret-derivation" class="section-name selfRef">Shared Secret Derivation</a>
|
||
</h5>
|
||
<p id="section-6.4.2.2-1">The OPAQUE-3DH shared secret derived during the key exchange protocol is
|
||
computed using the following helper function.<a href="#section-6.4.2.2-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.4.2.2-2">
|
||
<pre>
|
||
DeriveKeys
|
||
|
||
Input:
|
||
- ikm, input key material.
|
||
- preamble, the protocol transcript with identities and messages.
|
||
|
||
Output:
|
||
- Km2, a MAC authentication key.
|
||
- Km3, a MAC authentication key.
|
||
- session_key, the shared session secret.
|
||
|
||
def DeriveKeys(ikm, preamble):
|
||
prk = Extract("", ikm)
|
||
handshake_secret =
|
||
Derive-Secret(prk, "HandshakeSecret",Hash(preamble))
|
||
session_key =
|
||
Derive-Secret(prk, "SessionKey", Hash(preamble))
|
||
Km2 = Derive-Secret(handshake_secret, "ServerMAC", "")
|
||
Km3 = Derive-Secret(handshake_secret, "ClientMAC", "")
|
||
return (Km2, Km3, session_key)
|
||
</pre><a href="#section-6.4.2.2-2" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="ake-client">
|
||
<section id="section-6.4.3">
|
||
<h4 id="name-3dh-client-functions">
|
||
<a href="#section-6.4.3" class="section-number selfRef">6.4.3. </a><a href="#name-3dh-client-functions" class="section-name selfRef">3DH Client Functions</a>
|
||
</h4>
|
||
<p id="section-6.4.3-1">The <code>AuthClientStart</code> function is used by the client to create a
|
||
<code>KE1</code> structure.<a href="#section-6.4.3-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.4.3-2">
|
||
<pre>
|
||
AuthClientStart
|
||
|
||
Parameters:
|
||
- Nn, the nonce length.
|
||
|
||
State:
|
||
- state, a ClientAkeState structure.
|
||
|
||
Input:
|
||
- credential_request, a CredentialRequest structure.
|
||
|
||
Output:
|
||
- ke1, a KE1 structure.
|
||
|
||
def AuthClientStart(credential_request):
|
||
client_nonce = random(Nn)
|
||
client_keyshare_seed = random(Nseed)
|
||
(client_secret, client_public_keyshare) =
|
||
DeriveDiffieHellmanKeyPair(client_keyshare_seed)
|
||
|
||
auth_request = AuthRequest {
|
||
client_nonce,
|
||
client_public_keyshare
|
||
}
|
||
|
||
ke1 = KE1 {
|
||
credential_request,
|
||
auth_request
|
||
}
|
||
|
||
state.client_secret = client_secret
|
||
state.ke1 = ke1
|
||
return ke1
|
||
</pre><a href="#section-6.4.3-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-6.4.3-3">The <code>AuthClientFinalize</code> function is used by the client to create a <code>KE3</code>
|
||
message and output <code>session_key</code> using the server's <code>KE2</code> message and
|
||
recovered credential information.<a href="#section-6.4.3-3" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.4.3-4">
|
||
<pre>
|
||
AuthClientFinalize
|
||
|
||
State:
|
||
- state, a ClientAkeState structure.
|
||
|
||
Input:
|
||
- cleartext_credentials, a CleartextCredentials structure.
|
||
- client_private_key, the client's private key.
|
||
- ke2, a KE2 message structure.
|
||
|
||
Output:
|
||
- ke3, a KE3 structure.
|
||
- session_key, the shared session secret.
|
||
|
||
Exceptions:
|
||
- ServerAuthenticationError, the handshake fails.
|
||
|
||
def AuthClientFinalize(cleartext_credentials,
|
||
client_private_key, ke2):
|
||
|
||
dh1 = DiffieHellman(state.client_secret,
|
||
ke2.auth_response.server_public_keyshare)
|
||
dh2 = DiffieHellman(state.client_secret,
|
||
cleartext_credentials.server_public_key)
|
||
dh3 = DiffieHellman(client_private_key,
|
||
ke2.auth_response.server_public_keyshare)
|
||
ikm = concat(dh1, dh2, dh3)
|
||
|
||
preamble = Preamble(cleartext_credentials.client_identity,
|
||
state.ke1,
|
||
cleartext_credentials.server_identity,
|
||
ke2.credential_response,
|
||
ke2.auth_response.server_nonce,
|
||
ke2.auth_response.server_public_keyshare)
|
||
Km2, Km3, session_key = DeriveKeys(ikm, preamble)
|
||
expected_server_mac = MAC(Km2, Hash(preamble))
|
||
if !ct_equal(ke2.auth_response.server_mac, expected_server_mac),
|
||
raise ServerAuthenticationError
|
||
client_mac = MAC(Km3, Hash(concat(preamble, expected_server_mac)))
|
||
ke3 = KE3 {
|
||
client_mac
|
||
}
|
||
return (ke3, session_key)
|
||
</pre><a href="#section-6.4.3-4" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="ake-server">
|
||
<section id="section-6.4.4">
|
||
<h4 id="name-3dh-server-functions">
|
||
<a href="#section-6.4.4" class="section-number selfRef">6.4.4. </a><a href="#name-3dh-server-functions" class="section-name selfRef">3DH Server Functions</a>
|
||
</h4>
|
||
<p id="section-6.4.4-1">The <code>AuthServerRespond</code> function is used by the server to process the client's
|
||
<code>KE1</code> message and public credential information to create a <code>KE2</code> message.<a href="#section-6.4.4-1" class="pilcrow">¶</a></p>
|
||
<div class="breakable sourcecode" id="section-6.4.4-2">
|
||
<pre>
|
||
AuthServerRespond
|
||
|
||
Parameters:
|
||
- Nn, the nonce length.
|
||
|
||
State:
|
||
- state, a ServerAkeState structure.
|
||
|
||
Input:
|
||
- cleartext_credentials, a CleartextCredentials structure.
|
||
- server_private_key, the server's private key.
|
||
- client_public_key, the client's public key.
|
||
- ke1, a KE1 message structure.
|
||
|
||
Output:
|
||
- auth_response, an AuthResponse structure.
|
||
|
||
def AuthServerRespond(cleartext_credentials, server_private_key,
|
||
client_public_key, ke1, credential_response):
|
||
server_nonce = random(Nn)
|
||
server_keyshare_seed = random(Nseed)
|
||
(server_private_keyshare, server_public_keyshare) =
|
||
DeriveDiffieHellmanKeyPair(server_keyshare_seed)
|
||
preamble = Preamble(cleartext_credentials.client_identity,
|
||
ke1,
|
||
cleartext_credentials.server_identity,
|
||
credential_response,
|
||
server_nonce,
|
||
server_public_keyshare)
|
||
|
||
dh1 = DiffieHellman(server_private_keyshare,
|
||
ke1.auth_request.client_public_keyshare)
|
||
dh2 = DiffieHellman(server_private_key,
|
||
ke1.auth_request.client_public_keyshare)
|
||
dh3 = DiffieHellman(server_private_keyshare,
|
||
client_public_key)
|
||
ikm = concat(dh1, dh2, dh3)
|
||
|
||
Km2, Km3, session_key = DeriveKeys(ikm, preamble)
|
||
server_mac = MAC(Km2, Hash(preamble))
|
||
|
||
state.expected_client_mac =
|
||
MAC(Km3, Hash(concat(preamble, server_mac)))
|
||
state.session_key = session_key
|
||
|
||
auth_response = AuthResponse {
|
||
server_nonce,
|
||
server_public_keyshare,
|
||
server_mac
|
||
}
|
||
|
||
return auth_response
|
||
</pre><a href="#section-6.4.4-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="section-6.4.4-3">The <code>AuthServerFinalize</code> function is used by the server to process the client's
|
||
<code>KE3</code> message and output the final <code>session_key</code>.<a href="#section-6.4.4-3" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="section-6.4.4-4">
|
||
<pre>
|
||
AuthServerFinalize
|
||
|
||
State:
|
||
- state, a ServerAkeState structure.
|
||
|
||
Input:
|
||
- ke3, a KE3 structure.
|
||
|
||
Output:
|
||
- session_key, the shared session secret if and only if ke3 is valid.
|
||
|
||
Exceptions:
|
||
- ClientAuthenticationError, the handshake fails.
|
||
|
||
def AuthServerFinalize(ke3):
|
||
if !ct_equal(ke3.client_mac, state.expected_client_mac):
|
||
raise ClientAuthenticationError
|
||
return state.session_key
|
||
</pre><a href="#section-6.4.4-4" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="configurations">
|
||
<section id="section-7">
|
||
<h2 id="name-configurations">
|
||
<a href="#section-7" class="section-number selfRef">7. </a><a href="#name-configurations" class="section-name selfRef">Configurations</a>
|
||
</h2>
|
||
<p id="section-7-1">An OPAQUE-3DH configuration is a tuple (OPRF, KDF, MAC, Hash, KSF, Group, Context)
|
||
such that the following conditions are met:<a href="#section-7-1" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-7-2.1">
|
||
<p id="section-7-2.1.1">The OPRF protocol uses the <code>modeOPRF</code> configuration in <span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.1" class="relref">Section 3.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span> and
|
||
implements the interface in <a href="#dependencies" class="auto internal xref">Section 2</a>. Examples include ristretto255-SHA512
|
||
and P256-SHA256.<a href="#section-7-2.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-7-2.2">
|
||
<p id="section-7-2.2.1">The KDF, MAC, and Hash functions implement the interfaces in <a href="#dependencies" class="auto internal xref">Section 2</a>.
|
||
Examples include HKDF <span>[<a href="#RFC5869" class="cite xref">RFC5869</a>]</span> for the KDF, HMAC <span>[<a href="#RFC2104" class="cite xref">RFC2104</a>]</span> for the MAC,
|
||
and SHA-256 and SHA-512 for the Hash functions. If an extensible output function
|
||
such as SHAKE128 <span>[<a href="#FIPS202" class="cite xref">FIPS202</a>]</span> is used, then the output length <code>Nh</code> <span class="bcp14">MUST</span> be chosen
|
||
to align with the target security level of the OPAQUE configuration. For example,
|
||
if the target security parameter for the configuration is 128 bits, then <code>Nh</code> <span class="bcp14">SHOULD</span>
|
||
be at least 32 bytes.<a href="#section-7-2.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-7-2.3">
|
||
<p id="section-7-2.3.1">The KSF is determined by the application and implements the interface in
|
||
<a href="#dependencies" class="auto internal xref">Section 2</a>. As noted, collision resistance is required. Examples for KSF
|
||
include Argon2id <span>[<a href="#RFC9106" class="cite xref">RFC9106</a>]</span>, scrypt <span>[<a href="#RFC7914" class="cite xref">RFC7914</a>]</span>, and PBKDF2
|
||
<span>[<a href="#RFC8018" class="cite xref">RFC8018</a>]</span> with fixed parameter choices. See <a href="#app-considerations" class="auto internal xref">Section 8</a>
|
||
for more information about this choice of function.<a href="#section-7-2.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-7-2.4">
|
||
<p id="section-7-2.4.1">The Group mode identifies the group used in the OPAQUE-3DH AKE. This <span class="bcp14">SHOULD</span>
|
||
match that of the OPRF. For example, if the OPRF is ristretto255-SHA512,
|
||
then Group <span class="bcp14">SHOULD</span> be ristretto255.<a href="#section-7-2.4.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
<p id="section-7-3">Context is the shared parameter used to construct the <code>preamble</code> in <a href="#transcript-functions" class="auto internal xref">Section 6.4.2.1</a>.
|
||
This parameter <span class="bcp14">SHOULD</span> include any application-specific configuration information or
|
||
parameters that are needed to prevent cross-protocol or downgrade attacks.<a href="#section-7-3" class="pilcrow">¶</a></p>
|
||
<p id="section-7-4">Absent an application-specific profile, the following configurations are <span class="bcp14">RECOMMENDED</span>:<a href="#section-7-4" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-7-5.1">
|
||
<p id="section-7-5.1.1">ristretto255-SHA512, HKDF-SHA-512, HMAC-SHA-512, SHA-512,
|
||
Argon2id(S = zeroes(16), p = 4, T = <code>Nh</code>, m = 2^21, t = 1, v = 0x13, K = nil, X = nil, y = 2), ristretto255<a href="#section-7-5.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-7-5.2">
|
||
<p id="section-7-5.2.1">P256-SHA256, HKDF-SHA-256, HMAC-SHA-256, SHA-256,
|
||
Argon2id(S = zeroes(16), p = 4, T = <code>Nh</code>, m = 2^21, t = 1, v = 0x13, K = nil, X = nil, y = 2), P-256<a href="#section-7-5.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-7-5.3">
|
||
<p id="section-7-5.3.1">P256-SHA256, HKDF-SHA-256, HMAC-SHA-256, SHA-256,
|
||
scrypt(S = zeroes(16), N = 32768, r = 8, p = 1, dkLen = 32), P-256<a href="#section-7-5.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
<p id="section-7-6">The above recommended configurations target 128-bit security.<a href="#section-7-6" class="pilcrow">¶</a></p>
|
||
<p id="section-7-7">Future configurations may specify different combinations of dependent algorithms
|
||
with the following considerations:<a href="#section-7-7" class="pilcrow">¶</a></p>
|
||
<ol start="1" type="1" class="normal type-1" id="section-7-8">
|
||
<li id="section-7-8.1">
|
||
<p id="section-7-8.1.1">The size of AKE public and private keys -- <code>Npk</code> and <code>Nsk</code>, respectively -- must adhere
|
||
to the output length limitations of the KDF Expand function. If HKDF is used, this means
|
||
<code>Npk</code>, <code>Nsk</code> <= 255 * <code>Nx</code>, where <code>Nx</code> is the output size of the underlying hash function.
|
||
See <span>[<a href="#RFC5869" class="cite xref">RFC5869</a>]</span> for details.<a href="#section-7-8.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li id="section-7-8.2">
|
||
<p id="section-7-8.2.1">The output size of the Hash function <span class="bcp14">SHOULD</span> be long enough to produce a key for
|
||
MAC of suitable length. For example, if MAC is HMAC-SHA256, then <code>Nh</code> could be
|
||
32 bytes.<a href="#section-7-8.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ol>
|
||
</section>
|
||
</div>
|
||
<div id="app-considerations">
|
||
<section id="section-8">
|
||
<h2 id="name-application-considerations">
|
||
<a href="#section-8" class="section-number selfRef">8. </a><a href="#name-application-considerations" class="section-name selfRef">Application Considerations</a>
|
||
</h2>
|
||
<p id="section-8-1">Beyond choosing an appropriate configuration, there are several parameters that applications can use to control OPAQUE:<a href="#section-8-1" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-8-2.1">
|
||
<p id="section-8-2.1.1">Credential identifier: As described in <a href="#registration-phase" class="auto internal xref">Section 5</a>, this is a unique
|
||
handle to the client's credential being stored. In applications where there are alternate
|
||
client identities that accompany an account, such as a username or email address, this
|
||
identifier can be set to those alternate values. For simplicity, applications may choose
|
||
to set <code>credential_identifier</code> to be equal to <code>client_identity</code>. Applications
|
||
<span class="bcp14">MUST NOT</span> use the same credential identifier for multiple clients.<a href="#section-8-2.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-8-2.2">
|
||
<p id="section-8-2.2.1">Context information: As described in <a href="#configurations" class="auto internal xref">Section 7</a>, applications may include
|
||
a shared <code>context</code> string that is authenticated as part of the handshake. This parameter
|
||
<span class="bcp14">SHOULD</span> include any configuration information or parameters that are needed to prevent
|
||
cross-protocol or downgrade attacks. This <code>context</code> information is not sent over the
|
||
wire in any key exchange messages. However, applications may choose to send it alongside
|
||
key exchange messages if needed for their use case.<a href="#section-8-2.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-8-2.3">
|
||
<p id="section-8-2.3.1">Client and server identities: As described in <a href="#client-material" class="auto internal xref">Section 4</a>, clients
|
||
and servers are identified with their public keys by default. However, applications
|
||
may choose alternate identities that are pinned to these public keys. For example,
|
||
servers may use a domain name instead of a public key as their identifier.
|
||
|
||
Absent
|
||
alternate notions of identity, applications <span class="bcp14">SHOULD</span> set these identities to nil
|
||
and rely solely on public key information.<a href="#section-8-2.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-8-2.4">
|
||
<p id="section-8-2.4.1">Configuration and envelope updates: Applications may wish to update or change their
|
||
configuration or other parameters that affect the client's <code>RegistrationRecord</code> over
|
||
time. Some reasons for changing these are to use different cryptographic algorithms,
|
||
e.g., a different KSF with improved parameters, or to update key material that is
|
||
cryptographically bound to the <code>RegistrationRecord</code>, such as the server's public key
|
||
(<code>server_public_key</code>). Any such change will require users to reregister to create a
|
||
new <code>RegistrationRecord</code>. Supporting these types of updates can be helpful for applications
|
||
that anticipate such changes in their deployment setting.<a href="#section-8-2.4.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-8-2.5">
|
||
<p id="section-8-2.5.1">Password hardening parameters: Key stretching is done to help prevent password disclosure
|
||
in the event of server compromise; see <a href="#key-stretch" class="auto internal xref">Section 10.8</a>. There is no ideal or default
|
||
set of parameters, though relevant specifications for KSFs give some reasonable
|
||
defaults.<a href="#section-8-2.5.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-8-2.6">
|
||
<p id="section-8-2.6.1">Enumeration prevention: If servers
|
||
receive a credential request for a non-existent client, they <span class="bcp14">SHOULD</span> respond with a
|
||
"fake" response to prevent active client enumeration attacks as described in <a href="#create-credential-response" class="auto internal xref">Section 6.3.2.2</a>. Servers that
|
||
implement this mitigation <span class="bcp14">SHOULD</span> use the same configuration information (such as
|
||
the <code>oprf_seed</code>) for all clients; see <a href="#preventing-client-enumeration" class="auto internal xref">Section 10.9</a>. In settings
|
||
where this attack is not a concern, servers may choose to not support this functionality.<a href="#section-8-2.6.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-8-2.7">
|
||
<p id="section-8-2.7.1">Handling password changes: In the event of a password change, the client and
|
||
server can run the registration phase using the new password as a
|
||
fresh instance (ensuring to resample all random values). The resulting
|
||
registration <code>record</code> can then replace the previous <code>record</code> corresponding to
|
||
the client's old password registration.<a href="#section-8-2.7.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
</div>
|
||
<div id="implementation-considerations">
|
||
<section id="section-9">
|
||
<h2 id="name-implementation-consideratio">
|
||
<a href="#section-9" class="section-number selfRef">9. </a><a href="#name-implementation-consideratio" class="section-name selfRef">Implementation Considerations</a>
|
||
</h2>
|
||
<p id="section-9-1">This section documents considerations for OPAQUE implementations. This includes
|
||
implementation safeguards and error handling considerations.<a href="#section-9-1" class="pilcrow">¶</a></p>
|
||
<div id="implementation-safeguards">
|
||
<section id="section-9.1">
|
||
<h3 id="name-implementation-safeguards">
|
||
<a href="#section-9.1" class="section-number selfRef">9.1. </a><a href="#name-implementation-safeguards" class="section-name selfRef">Implementation Safeguards</a>
|
||
</h3>
|
||
<p id="section-9.1-1">Certain information created, exchanged, and processed in OPAQUE is sensitive.
|
||
Specifically, all private key material and intermediate values, along with the
|
||
outputs of the key exchange phase, are all secret. Implementations should not
|
||
retain these values in memory when no longer needed. Moreover, all operations,
|
||
particularly the cryptographic and group arithmetic operations, should be
|
||
constant-time and independent of the bits of any secrets. This includes any
|
||
conditional branching during the creation of the credential response as needed
|
||
to mitigate client enumeration attacks.<a href="#section-9.1-1" class="pilcrow">¶</a></p>
|
||
<p id="section-9.1-2">As specified in <a href="#registration-phase" class="auto internal xref">Section 5</a> and <a href="#online-phase" class="auto internal xref">Section 6</a>, OPAQUE only requires
|
||
the client password as input to the OPRF for registration and authentication.
|
||
However, if <code>client_identity</code> can be bound to the client's registration <code>record</code>
|
||
(i.e., the identity will not change during the lifetime of the <code>record</code>),
|
||
then an implementation <span class="bcp14">SHOULD</span> incorporate <code>client_identity</code> alongside the
|
||
password as input to the OPRF. Furthermore, it is <span class="bcp14">RECOMMENDED</span> to incorporate
|
||
<code>server_identity</code> alongside the password as input to the OPRF. These
|
||
additions provide domain separation for clients and servers; see
|
||
<a href="#security-analysis" class="auto internal xref">Section 10.2</a>.<a href="#section-9.1-2" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="handling-online-guessing-attacks">
|
||
<section id="section-9.2">
|
||
<h3 id="name-handling-online-guessing-at">
|
||
<a href="#section-9.2" class="section-number selfRef">9.2. </a><a href="#name-handling-online-guessing-at" class="section-name selfRef">Handling Online Guessing Attacks</a>
|
||
</h3>
|
||
<p id="section-9.2-1">Online guessing attacks (against any aPAKE) can be done from
|
||
both the client side and the server side. In particular, a malicious server can
|
||
attempt to simulate honest responses to learn the client's password.
|
||
While this constitutes an exhaustive online attack (as expensive as a guessing
|
||
attack from the client side), it can be mitigated when the channel between
|
||
client and server is authenticated, e.g., using server-authenticated TLS. In
|
||
such cases, these online attacks are limited to clients and the authenticated
|
||
server itself. Moreover, such a channel provides privacy of user information,
|
||
including identity and envelope values.<a href="#section-9.2-1" class="pilcrow">¶</a></p>
|
||
<p id="section-9.2-2">Additionally, note that a client participating in the online login stage
|
||
will learn whether or not authentication is successful after receiving the
|
||
<code>KE2</code> message. This means that the server should treat any client which fails to
|
||
send a subsequent <code>KE3</code> message as an authentication failure. This can be handled
|
||
in applications that wish to track authentication failures by, for example,
|
||
assuming by default that any client authentication attempt is a failure unless a <code>KE3</code>
|
||
message is received by the server and passes <code>ServerFinish</code> without error.<a href="#section-9.2-2" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="error-considerations">
|
||
<section id="section-9.3">
|
||
<h3 id="name-error-considerations">
|
||
<a href="#section-9.3" class="section-number selfRef">9.3. </a><a href="#name-error-considerations" class="section-name selfRef">Error Considerations</a>
|
||
</h3>
|
||
<p id="section-9.3-1">Some functions included in this specification are fallible. For example, the
|
||
authenticated key exchange protocol may fail because the client's password was
|
||
incorrect or the authentication check failed, yielding an error. The explicit
|
||
errors generated throughout this specification, along with conditions that lead
|
||
to each error, are as follows:<a href="#section-9.3-1" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-9.3-2.1">
|
||
<p id="section-9.3-2.1.1"><code>EnvelopeRecoveryError</code>: The <code>Envelope</code> <code>Recover</code> function failed to produce any
|
||
authentication key material; <a href="#envelope-recovery" class="auto internal xref">Section 4.1.3</a>.<a href="#section-9.3-2.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-9.3-2.2">
|
||
<p id="section-9.3-2.2.1">ServerAuthenticationError: The client failed to complete the authenticated
|
||
key exchange protocol with the server; <a href="#ake-client" class="auto internal xref">Section 6.4.3</a>.<a href="#section-9.3-2.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-9.3-2.3">
|
||
<p id="section-9.3-2.3.1"><code>ClientAuthenticationError</code>: The server failed to complete the authenticated
|
||
key exchange protocol with the client; <a href="#ake-server" class="auto internal xref">Section 6.4.4</a>.<a href="#section-9.3-2.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
<p id="section-9.3-3">Beyond these explicit errors, OPAQUE implementations can produce implicit errors.
|
||
For example, if protocol messages sent between client and server do not match
|
||
their expected size, an implementation should produce an error. More generally,
|
||
if any protocol message received from the peer is invalid, perhaps because the
|
||
message contains an invalid public key (indicated by the AKE DeserializeElement
|
||
function failing) or an invalid OPRF element (indicated by the OPRF DeserializeElement),
|
||
then an implementation should produce an error.<a href="#section-9.3-3" class="pilcrow">¶</a></p>
|
||
<p id="section-9.3-4">The errors in this document are meant as a guide for implementors. They are not an
|
||
exhaustive list of all the errors an implementation might emit. For example, an
|
||
implementation might run out of memory.<a href="#section-9.3-4" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="security-considerations">
|
||
<section id="section-10">
|
||
<h2 id="name-security-considerations">
|
||
<a href="#section-10" class="section-number selfRef">10. </a><a href="#name-security-considerations" class="section-name selfRef">Security Considerations</a>
|
||
</h2>
|
||
<p id="section-10-1">OPAQUE is defined as the composition of two functionalities: an OPRF and
|
||
an AKE protocol. It can be seen as a "compiler" for transforming any AKE
|
||
protocol (with Key Compromise Impersonation (KCI) security and forward secrecy; see <a href="#security-analysis" class="auto internal xref">Section 10.2</a>)
|
||
into a secure aPAKE protocol. In OPAQUE, the client derives a private key
|
||
during password registration and retrieves this key each time
|
||
it needs to authenticate to the server. The OPRF security properties
|
||
ensure that only the correct password can unlock the private key
|
||
while at the same time avoiding potential offline guessing attacks.
|
||
This general composability property provides great flexibility and
|
||
enables a variety of OPAQUE instantiations, from optimized
|
||
performance to integration with existing authenticated key exchange
|
||
protocols such as TLS.<a href="#section-10-1" class="pilcrow">¶</a></p>
|
||
<div id="notable-design-differences">
|
||
<section id="section-10.1">
|
||
<h3 id="name-notable-design-differences">
|
||
<a href="#section-10.1" class="section-number selfRef">10.1. </a><a href="#name-notable-design-differences" class="section-name selfRef">Notable Design Differences</a>
|
||
</h3>
|
||
<p id="section-10.1-1">The specification as written here differs from the original cryptographic design in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>
|
||
and the corresponding CFRG document <span>[<a href="#I-D.krawczyk-cfrg-opaque" class="cite xref">Krawczyk20</a>]</span>, both of which were used
|
||
as input to the CFRG PAKE competition. This section describes these differences, including
|
||
their motivation and explanation as to why they preserve the provable security of OPAQUE based
|
||
on <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>.<a href="#section-10.1-1" class="pilcrow">¶</a></p>
|
||
<p id="section-10.1-2">The following list enumerates important functional differences that were made
|
||
as part of the protocol specification process to address application or
|
||
implementation considerations.<a href="#section-10.1-2" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-10.1-3.1">
|
||
<p id="section-10.1-3.1.1">Clients construct envelope contents without revealing the password to the
|
||
server, as described in <a href="#registration-phase" class="auto internal xref">Section 5</a>, whereas the servers construct
|
||
envelopes in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>. This change adds to the security of the protocol.
|
||
<span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> considered the case where the envelope was constructed by the
|
||
server for reasons of compatibility with previous Universal Composability (UC) security modeling. <span>[<a href="#HJKW23" class="cite xref">HJKW23</a>]</span>
|
||
analyzes the registration phase as specified in this document. This
|
||
change was made to support registration flows where the client chooses the
|
||
password and wishes to keep it secret from the server, and it is compatible
|
||
with the variant in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> that was originally analyzed.<a href="#section-10.1-3.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.2">
|
||
<p id="section-10.1-3.2.1">Envelopes do not contain encrypted credentials. Instead, envelopes contain
|
||
information used to derive client private key material for the AKE.
|
||
This change improves the assumption behind the protocol by getting rid of
|
||
equivocality and random key robustness for the encryption function.
|
||
The random-key robustness property defined in <a href="#deps-symmetric" class="auto internal xref">Section 2.2</a> is only
|
||
needed for the MAC function. This change was made for two reasons. First, it
|
||
reduces the number of bytes stored in envelopes, which is a helpful
|
||
improvement for large applications of OPAQUE with many registered users.
|
||
Second, it removes the need for client applications to generate private
|
||
keys during registration. Instead, this responsibility is handled by OPAQUE,
|
||
thereby simplifying the client interface to the protocol.<a href="#section-10.1-3.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.3">
|
||
<p id="section-10.1-3.3.1">Envelopes are masked with a per-user masking key as a way of preventing
|
||
client enumeration attacks. See <a href="#preventing-client-enumeration" class="auto internal xref">Section 10.9</a> for more
|
||
details. This extension is not needed for the security of OPAQUE as an aPAKE protocol,
|
||
but is only used to provide a defense against enumeration attacks. In the
|
||
analysis, the masking key can be simulated as a (pseudo) random key. This
|
||
change was made to support real-world use cases where client or user
|
||
enumeration is a security (or privacy) risk.<a href="#section-10.1-3.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.4">
|
||
<p id="section-10.1-3.4.1">Per-user OPRF keys are derived from a client identity and cross-user PRF <code>seed</code>
|
||
as a mitigation against client enumeration attacks. See
|
||
<a href="#preventing-client-enumeration" class="auto internal xref">Section 10.9</a> for more details. The analysis of OPAQUE
|
||
assumes OPRF keys of different users are independently random or
|
||
pseudorandom. Deriving these keys via a single PRF (i.e., with a single
|
||
cross-user key) applied to users' identities satisfies this assumption.
|
||
This change was made to support real-world use cases where client or user
|
||
enumeration is a security (or privacy) risk. Note that the derivation of the
|
||
OPRF key via a PRF keyed by <code>oprf_seed</code> and applied to the unique
|
||
<code>credential_identifier</code> ensures the critical requirement of the per-user OPRF keys
|
||
being unique per client.<a href="#section-10.1-3.4.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.5">
|
||
<p id="section-10.1-3.5.1">The protocol outputs an export key for the client in addition to a shared
|
||
session key that can be used for application-specific purposes. This key
|
||
is a pseudorandom value derived from the client password (among other values) and
|
||
has no influence on the security analysis (it can be simulated with a
|
||
random output). This change was made to support more application use cases
|
||
for OPAQUE, such as the use of OPAQUE for end-to-end encrypted backups;
|
||
see <span>[<a href="#WhatsAppE2E" class="cite xref">WhatsAppE2E</a>]</span>.<a href="#section-10.1-3.5.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.6">
|
||
<p id="section-10.1-3.6.1">The AKE protocol describes a 3-message protocol where the third message includes client
|
||
authentication material that the server is required to verify. This change
|
||
(from the original 2-message protocol) was made to provide explicit client
|
||
authentication and full forward security. The 3-message protocol is analyzed
|
||
in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>.<a href="#section-10.1-3.6.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.7">
|
||
<p id="section-10.1-3.7.1">The protocol admits optional application-layer client and server identities.
|
||
In the absence of these identities, the client and server are authenticated
|
||
against their public keys. Binding authentication to identities is part
|
||
of the AKE part of OPAQUE. The type of identities and their semantics
|
||
are application-dependent and independent of the protocol analysis. This
|
||
change was made to simplify client and server interfaces to the protocol
|
||
by removing the need to specify additional identities alongside their
|
||
corresponding public authentication keys when not needed.<a href="#section-10.1-3.7.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.8">
|
||
<p id="section-10.1-3.8.1">The protocol admits application-specific <code>context</code> information configured
|
||
out-of-band in the AKE transcript. This allows domain separation between
|
||
different application uses of OPAQUE. This is a mechanism for the AKE
|
||
component and is best practice for domain separation between different
|
||
applications of the protocol. This change was made to allow different
|
||
applications to use OPAQUE without the risk of cross-protocol attacks.<a href="#section-10.1-3.8.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.9">
|
||
<p id="section-10.1-3.9.1">Servers use a separate identifier for computing OPRF evaluations and
|
||
indexing into the registration <code>record</code> storage called the <code>credential_identifier</code>.
|
||
This allows clients to change their application-layer identity
|
||
(<code>client_identity</code>) without inducing server-side changes, e.g., by changing
|
||
an email address associated with a given account. This mechanism is part
|
||
of the derivation of OPRF keys via a single PRF. As long as the derivation
|
||
of different OPRF keys from a single PRF has different PRF inputs, the
|
||
protocol is secure. The choice of such inputs is up to the application.<a href="#section-10.1-3.9.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-3.10">
|
||
<p id="section-10.1-3.10.1"><span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> comments on a defense against offline
|
||
dictionary attacks upon server compromise or honest-but-curious servers.
|
||
|
||
The authors suggest implementing the OPRF phase as a threshold OPRF <span>[<a href="#TOPPSS" class="cite xref">TOPPSS</a>]</span>, effectively forcing an attacker to act online or
|
||
control at least t key shares (of the total n), where t is the threshold
|
||
number of shares necessary to recombine the secret OPRF key. Only then
|
||
would an attacker be able to run an offline dictionary attack. This
|
||
implementation only affects the server and changes nothing for the client.
|
||
Furthermore, if the threshold OPRF servers holding these keys are separate
|
||
from the authentication server, then recovering all n shares would still
|
||
not suffice to run an offline dictionary attack without access to the
|
||
client <code>record</code> database. However, this mechanism is out of scope for this
|
||
document.<a href="#section-10.1-3.10.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
<p id="section-10.1-4">The following list enumerates notable differences and refinements from the original
|
||
cryptographic design in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> and the corresponding CFRG document
|
||
<span>[<a href="#I-D.krawczyk-cfrg-opaque" class="cite xref">Krawczyk20</a>]</span> that were made to make this specification
|
||
suitable for interoperable implementations.<a href="#section-10.1-4" class="pilcrow">¶</a></p>
|
||
<ul class="normal">
|
||
<li class="normal" id="section-10.1-5.1">
|
||
<p id="section-10.1-5.1.1"><span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> used a generic prime-order group for the DH-OPRF and HMQV operations,
|
||
and includes necessary prime-order subgroup checks when receiving attacker-controlled
|
||
values over the wire. This specification instantiates the prime-order group used for
|
||
3DH using prime-order groups based on elliptic curves as described in
|
||
<span><a href="https://rfc-editor.org/rfc/rfc9497#section-2.1" class="relref">Section 2.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>. This specification also delegates OPRF group
|
||
choice and operations to <span><a href="https://rfc-editor.org/rfc/rfc9497#section-4" class="relref">Section 4</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>. As such, the prime-order group as used
|
||
in the OPRF and 3DH as specified in this document both adhere to the requirements in
|
||
<span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>.<a href="#section-10.1-5.1.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-5.2">
|
||
<p id="section-10.1-5.2.1">Appendix B of <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> specified DH-OPRF to instantiate
|
||
the OPRF functionality in the protocol. A critical part of DH-OPRF is the
|
||
hash-to-group operation, which was not instantiated in the original analysis.
|
||
However, the requirements for this operation were included. This specification
|
||
instantiates the OPRF functionality based on <span><a href="https://rfc-editor.org/rfc/rfc9497#section-3.3.1" class="relref">Section 3.3.1</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span>, which
|
||
is identical to the DH-OPRF functionality in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> and, concretely, uses
|
||
the hash-to-curve functions in <span>[<a href="#RFC9380" class="cite xref">RFC9380</a>]</span>. All hash-to-curve
|
||
methods in <span>[<a href="#RFC9380" class="cite xref">RFC9380</a>]</span> are compliant with the requirement
|
||
in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>, namely, that the output be a member of the prime-order group.<a href="#section-10.1-5.2.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-5.3">
|
||
<p id="section-10.1-5.3.1"><span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> and <span>[<a href="#I-D.krawczyk-cfrg-opaque" class="cite xref">Krawczyk20</a>]</span> both used HMQV as the AKE
|
||
for the protocol. However, this document fully specifies 3DH instead of HMQV
|
||
(though a sketch for how to instantiate OPAQUE using HMQV is included in <a href="#hmqv-sketch" class="auto internal xref">Appendix B.1</a>).
|
||
Since 3DH satisfies the essential requirements for the AKE protocol as described in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>
|
||
and <span>[<a href="#I-D.krawczyk-cfrg-opaque" class="cite xref">Krawczyk20</a>]</span>, as recalled in <a href="#security-analysis" class="auto internal xref">Section 10.2</a>, this change
|
||
preserves the overall security of the protocol. 3DH was chosen for its
|
||
simplicity and ease of implementation.<a href="#section-10.1-5.3.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-5.4">
|
||
<p id="section-10.1-5.4.1">The DH-OPRF and HMQV instantiation of OPAQUE as shown in Figure 12 <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> uses
|
||
a different transcript than that which is described in this specification. In particular,
|
||
the key exchange transcript specified in <a href="#protocol-3dh" class="auto internal xref">Section 6.4</a> is a superset of the transcript
|
||
as defined in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>. This was done to align with best practices, like what is done for key exchange protocols like TLS 1.3 <span>[<a href="#RFC8446" class="cite xref">RFC8446</a>]</span>.<a href="#section-10.1-5.4.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
<li class="normal" id="section-10.1-5.5">
|
||
<p id="section-10.1-5.5.1">Neither <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> nor <span>[<a href="#I-D.krawczyk-cfrg-opaque" class="cite xref">Krawczyk20</a>]</span> included wire format details for the
|
||
protocol, which is essential for interoperability. This specification fills this
|
||
gap by including such wire format details and corresponding test vectors; see <a href="#test-vectors" class="auto internal xref">Appendix C</a>.<a href="#section-10.1-5.5.1" class="pilcrow">¶</a></p>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
</div>
|
||
<div id="security-analysis">
|
||
<section id="section-10.2">
|
||
<h3 id="name-security-analysis">
|
||
<a href="#section-10.2" class="section-number selfRef">10.2. </a><a href="#name-security-analysis" class="section-name selfRef">Security Analysis</a>
|
||
</h3>
|
||
<p id="section-10.2-1">Jarecki et al. <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> proved the security of OPAQUE (modulo the
|
||
design differences outlined in <a href="#notable-design-differences" class="auto internal xref">Section 10.1</a>)
|
||
in a strong aPAKE model that ensures security against precomputation attacks
|
||
and is formulated in the UC framework <span>[<a href="#Canetti01" class="cite xref">Canetti01</a>]</span>
|
||
under the random oracle model. This assumes security of the OPRF
|
||
function and the underlying key exchange protocol.<a href="#section-10.2-1" class="pilcrow">¶</a></p>
|
||
<p id="section-10.2-2">OPAQUE's design builds on a line of work initiated in the seminal
|
||
paper of Ford and Kaliski <span>[<a href="#FK00" class="cite xref">FK00</a>]</span> and is based on the HPAKE protocol
|
||
of Xavier Boyen <span>[<a href="#Boyen09" class="cite xref">Boyen09</a>]</span> and the (1,1)-PPSS protocol from Jarecki
|
||
et al. <span>[<a href="#JKKX16" class="cite xref">JKKX16</a>]</span>. None of these papers considered security against
|
||
precomputation attacks or presented a proof of aPAKE security
|
||
(not even in a weak model).<a href="#section-10.2-2" class="pilcrow">¶</a></p>
|
||
<p id="section-10.2-3">The KCI property required from AKE protocols for use with OPAQUE
|
||
states that knowledge of a party's private key does not allow an attacker
|
||
to impersonate others to that party. This is an important security
|
||
property achieved by most public-key-based AKE protocols, including
|
||
protocols that use signatures or public key encryption for
|
||
authentication. It is also a property of many implicitly
|
||
authenticated protocols, e.g., HMQV, but not all of them. We also note that
|
||
key exchange protocols based on shared keys do not satisfy the KCI
|
||
requirement, hence they are not considered in the OPAQUE setting.
|
||
We note that KCI is needed to ensure a crucial property of OPAQUE. Even upon
|
||
compromise of the server, the attacker cannot impersonate the client to the
|
||
server without first running an exhaustive dictionary attack.
|
||
Another essential requirement from AKE protocols for use in OPAQUE is to
|
||
provide forward secrecy (against active attackers).<a href="#section-10.2-3" class="pilcrow">¶</a></p>
|
||
<p id="section-10.2-4">In <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span>, security is proven for one instance (i.e., one
|
||
key) of the OPAQUE protocol, and without batching. There is currently no
|
||
security analysis available for the OPAQUE protocol described in this
|
||
document in a setting with multiple server keys or batching.<a href="#section-10.2-4" class="pilcrow">¶</a></p>
|
||
<p id="section-10.2-5">As stated in <a href="#implementation-safeguards" class="auto internal xref">Section 9.1</a>, incorporating <code>client_identity</code>
|
||
adds domain separation, particularly against servers that choose the same
|
||
OPRF key for multiple clients. The <code>client_identity</code> as input to the OPRF
|
||
also acts as a key identifier that would be required for a proof of the
|
||
protocol in the multi-key setting; the OPAQUE analysis in <span>[<a href="#JKX18" class="cite xref">JKX18</a>]</span> assumes
|
||
single server-key instances. Adding <code>server_identity</code> to the OPRF input
|
||
provides domain separation for clients that reuse the same <code>client_identity</code>
|
||
across different server instantiations.<a href="#section-10.2-5" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="identities">
|
||
<section id="section-10.3">
|
||
<h3 id="name-identities">
|
||
<a href="#section-10.3" class="section-number selfRef">10.3. </a><a href="#name-identities" class="section-name selfRef">Identities</a>
|
||
</h3>
|
||
<p id="section-10.3-1">AKE protocols generate keys that need to be uniquely and verifiably bound to a pair
|
||
of identities. In the case of OPAQUE, those identities correspond to <code>client_identity</code> and <code>server_identity</code>.
|
||
Thus, it is essential for the parties to agree on such identities, including an
|
||
agreed bit representation of these identities as needed.<a href="#section-10.3-1" class="pilcrow">¶</a></p>
|
||
<p id="section-10.3-2">Note that the method of transmission of <code>client_identity</code> from client to server is outside
|
||
the scope of this protocol and it is up to an application to choose how this identity
|
||
should be delivered (for instance, alongside the first OPAQUE message or agreed upon before
|
||
the OPAQUE protocol begins).<a href="#section-10.3-2" class="pilcrow">¶</a></p>
|
||
<p id="section-10.3-3">Applications may have different policies about how and when identities are
|
||
determined. A natural approach is to tie <code>client_identity</code> to the identity the server uses
|
||
to fetch the envelope (determined during password registration) and tie <code>server_identity</code>
|
||
to the server identity used by the client to initiate an offline password
|
||
registration or online authenticated key exchange session. <code>server_identity</code> and <code>client_identity</code> can also
|
||
be part of the envelope or tied to the parties' public keys. In principle, identities
|
||
may change across different sessions as long as there is a policy that
|
||
can establish if the identity is acceptable or not to the peer. However, we note
|
||
that the public keys of both the server and the client must always be those defined
|
||
at the time of password registration.<a href="#section-10.3-3" class="pilcrow">¶</a></p>
|
||
<p id="section-10.3-4">The client identity (<code>client_identity</code>) and server identity (<code>server_identity</code>) are
|
||
optional parameters that are left to the application to designate as aliases for
|
||
the client and server. If the application layer does not supply values for these
|
||
parameters, then they will be omitted from the creation of the envelope
|
||
during the registration stage. Furthermore, they will be substituted with
|
||
<code>client_identity</code> = <code>client_public_key</code> and <code>server_identity</code> = <code>server_public_key</code> during
|
||
the authenticated key exchange stage.<a href="#section-10.3-4" class="pilcrow">¶</a></p>
|
||
<p id="section-10.3-5">The advantage of supplying a custom <code>client_identity</code> and <code>server_identity</code> (instead of simply relying
|
||
on a fallback to <code>client_public_key</code> and <code>server_public_key</code>) is that the client can then ensure that any
|
||
mappings between <code>client_identity</code> and <code>client_public_key</code> (and <code>server_identity</code> and <code>server_public_key</code>)
|
||
are protected by the authentication from the envelope. Then, the client can verify that the
|
||
<code>client_identity</code> and <code>server_identity</code> contained in its envelope match the <code>client_identity</code>
|
||
and <code>server_identity</code> supplied by the server.<a href="#section-10.3-5" class="pilcrow">¶</a></p>
|
||
<p id="section-10.3-6">However, if this extra layer of verification is unnecessary for the application, then simply
|
||
leaving <code>client_identity</code> and <code>server_identity</code> unspecified (and using <code>client_public_key</code> and
|
||
<code>server_public_key</code> instead) is acceptable.<a href="#section-10.3-6" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="export-key-usage">
|
||
<section id="section-10.4">
|
||
<h3 id="name-export-key-usage">
|
||
<a href="#section-10.4" class="section-number selfRef">10.4. </a><a href="#name-export-key-usage" class="section-name selfRef">Export Key Usage</a>
|
||
</h3>
|
||
<p id="section-10.4-1">The export key can be used (separately from the OPAQUE protocol) to provide
|
||
confidentiality and integrity to other data that only the client should be
|
||
able to process. For instance, if the client wishes to store secrets with a
|
||
third party, then this export key can be used by the client to encrypt these
|
||
secrets so that they remain hidden from a passive adversary that does not have
|
||
access to the server's secret keys or the client's password.<a href="#section-10.4-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="static-diffie-hellman-oracles">
|
||
<section id="section-10.5">
|
||
<h3 id="name-static-diffie-hellman-oracl">
|
||
<a href="#section-10.5" class="section-number selfRef">10.5. </a><a href="#name-static-diffie-hellman-oracl" class="section-name selfRef">Static Diffie-Hellman Oracles</a>
|
||
</h3>
|
||
<p id="section-10.5-1">While one can expect the practical security of the OPRF function (namely,
|
||
the hardness of computing the function without knowing the key) to be in the
|
||
order of computing discrete logarithms or solving Diffie-Hellman, Brown and
|
||
Gallant <span>[<a href="#BG04" class="cite xref">BG04</a>]</span> and Cheon <span>[<a href="#Cheon06" class="cite xref">Cheon06</a>]</span> show an attack that slightly improves
|
||
on generic attacks. For typical curves, the attack requires an infeasible
|
||
number of calls to the OPRF or results in insignificant security loss;
|
||
see <span><a href="https://rfc-editor.org/rfc/rfc9497#section-7.2.3" class="relref">Section 7.2.3</a> of [<a href="#RFC9497" class="cite xref">RFC9497</a>]</span> for more information. For OPAQUE, these attacks
|
||
are particularly impractical as they translate into an infeasible number of
|
||
failed authentication attempts directed at individual users.<a href="#section-10.5-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="rkr-mac">
|
||
<section id="section-10.6">
|
||
<h3 id="name-random-key-robust-macs">
|
||
<a href="#section-10.6" class="section-number selfRef">10.6. </a><a href="#name-random-key-robust-macs" class="section-name selfRef">Random-Key Robust MACs</a>
|
||
</h3>
|
||
<p id="section-10.6-1">The random-key robustness property for a MAC states
|
||
that, given two random keys k1 and k2, it is infeasible to find a message m
|
||
such that MAC(k1, m) = MAC(k2, m). Note that in general, not every MAC function
|
||
is key-robust. In particular, GMAC (which underlies GCM) does not satisfy
|
||
key-robustness, whereas HMAC with a collision-resistant hash function does
|
||
satisfy key-robustness.<a href="#section-10.6-1" class="pilcrow">¶</a></p>
|
||
<p id="section-10.6-2">An application can choose to use a non-key-robust MAC within the AKE portion of
|
||
the protocol described in <a href="#protocol-3dh" class="auto internal xref">Section 6.4</a>, but it <span class="bcp14">MUST</span> use a key-robust MAC
|
||
for the creation of the <code>auth_tag</code> parameter in <a href="#envelope-creation" class="auto internal xref">Section 4.1.2</a>.<a href="#section-10.6-2" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="validation">
|
||
<section id="section-10.7">
|
||
<h3 id="name-input-validation">
|
||
<a href="#section-10.7" class="section-number selfRef">10.7. </a><a href="#name-input-validation" class="section-name selfRef">Input Validation</a>
|
||
</h3>
|
||
<p id="section-10.7-1">Both client and server <span class="bcp14">MUST</span> validate the other party's public key(s) used
|
||
for the execution of OPAQUE. This includes the keys shared during the
|
||
registration phase, as well as any keys shared during the online
|
||
key agreement phase. The validation procedure varies depending on the
|
||
type of key. For example, for OPAQUE instantiations
|
||
using 3DH with P-256, P-384, or P-521 as the underlying group, validation
|
||
is as specified in Section 5.6.2.3.4 of <span>[<a href="#keyagreement" class="cite xref">keyagreement</a>]</span>. This includes
|
||
checking that the coordinates are in the correct range, that the point
|
||
is on the curve, and that the point is not the point at infinity.
|
||
Additionally, validation <span class="bcp14">MUST</span> ensure the Diffie-Hellman shared secret is
|
||
not the point at infinity.<a href="#section-10.7-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="key-stretch">
|
||
<section id="section-10.8">
|
||
<h3 id="name-oprf-key-stretching">
|
||
<a href="#section-10.8" class="section-number selfRef">10.8. </a><a href="#name-oprf-key-stretching" class="section-name selfRef">OPRF Key Stretching</a>
|
||
</h3>
|
||
<p id="section-10.8-1">Applying a key stretching function to the output of the OPRF greatly increases the cost of an offline
|
||
attack upon the compromise of the credential file on the server. Applications
|
||
<span class="bcp14">SHOULD</span> select parameters for the KSF that balance cost and complexity across
|
||
different client implementations and deployments. Note that in OPAQUE, the
|
||
key stretching function is executed by the client as opposed to the server in
|
||
common password hashing scenarios. This means that applications must consider
|
||
a tradeoff between the performance of the protocol on clients (specifically low-end
|
||
devices) and protection against offline attacks after a server compromise.<a href="#section-10.8-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="preventing-client-enumeration">
|
||
<section id="section-10.9">
|
||
<h3 id="name-client-enumeration">
|
||
<a href="#section-10.9" class="section-number selfRef">10.9. </a><a href="#name-client-enumeration" class="section-name selfRef">Client Enumeration</a>
|
||
</h3>
|
||
<p id="section-10.9-1">Client enumeration refers to attacks where the attacker tries to learn whether
|
||
a given user identity is registered with a server or whether a reregistration
|
||
or change of password was performed for that user. OPAQUE counters these
|
||
attacks by requiring servers to act with unregistered client identities in a
|
||
way that is indistinguishable from their behavior with existing registered clients.
|
||
Servers do this by simulating a fake <code>CredentialResponse</code> as specified in
|
||
<a href="#create-credential-response" class="auto internal xref">Section 6.3.2.2</a> for unregistered users and encrypting
|
||
<code>CredentialResponse</code> using a masking key. In this way, real and fake <code>CredentialResponse</code>
|
||
messages are indistinguishable from one another.
|
||
Implementations must also take care to avoid side-channel leakage (e.g., timing
|
||
attacks) from helping differentiate these operations from a regular server
|
||
response. Note that this may introduce possible abuse vectors since the
|
||
server's cost of generating a <code>CredentialResponse</code> is less than that of the
|
||
client's cost of generating a <code>CredentialRequest</code>. Server implementations
|
||
may choose to forego the construction of a simulated credential response
|
||
message for an unregistered client if these client enumeration attacks can
|
||
be mitigated through other application-specific means or are otherwise not
|
||
applicable for their threat model.<a href="#section-10.9-1" class="pilcrow">¶</a></p>
|
||
<p id="section-10.9-2">OPAQUE does not prevent this type of attack during the registration flow.
|
||
Servers necessarily react differently during the registration flow between
|
||
registered and unregistered clients. This allows an attacker to use the server's
|
||
response during registration as an oracle for whether a given client identity is
|
||
registered. Applications should mitigate against this type of attack by rate
|
||
limiting or otherwise restricting the registration flow.<a href="#section-10.9-2" class="pilcrow">¶</a></p>
|
||
<p id="section-10.9-3">Finally, applications that do not require protection against
|
||
client enumeration attacks can choose to derive independent OPRF keys for different
|
||
clients. The advantage to using independently-derived OPRF keys is that the server
|
||
avoids keeping the <code>oprf_seed</code> value across different clients, which, if leaked, would
|
||
compromise the security for all clients reliant on <code>oprf_seed</code> as noted in <span>[<a href="#DL24" class="cite xref">DL24</a>]</span>.<a href="#section-10.9-3" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="protecting-the-registration-masking-key">
|
||
<section id="section-10.10">
|
||
<h3 id="name-protecting-the-registration">
|
||
<a href="#section-10.10" class="section-number selfRef">10.10. </a><a href="#name-protecting-the-registration" class="section-name selfRef">Protecting the Registration Masking Key</a>
|
||
</h3>
|
||
<p id="section-10.10-1">The user enumeration prevention method described in this document uses a
|
||
symmetric encryption key, <code>masking_key</code>, generated and sent to the server
|
||
by the client during registration. This requires a confidential channel
|
||
between client and server during registration, e.g., using TLS <span>[<a href="#RFC8446" class="cite xref">RFC8446</a>]</span>.
|
||
If the channel is only authenticated (this is a requirement for correct
|
||
identification of the parties), a confidential channel can be established
|
||
using public-key encryption, e.g., with HPKE <span>[<a href="#RFC9180" class="cite xref">RFC9180</a>]</span>. However, the details
|
||
of this mechanism are out of scope for this document.<a href="#section-10.10-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="password-salt-and-storage-implications">
|
||
<section id="section-10.11">
|
||
<h3 id="name-password-salt-and-storage-i">
|
||
<a href="#section-10.11" class="section-number selfRef">10.11. </a><a href="#name-password-salt-and-storage-i" class="section-name selfRef">Password Salt and Storage Implications</a>
|
||
</h3>
|
||
<p id="section-10.11-1">In OPAQUE, the OPRF key acts as the secret <code>salt</code> value that ensures the infeasibility
|
||
of precomputation attacks. No extra <code>salt</code> value is needed. Also, clients never
|
||
disclose their passwords to the server, even during registration. Note that a corrupted
|
||
server can run an exhaustive offline dictionary attack to validate guesses for the client's
|
||
password; this is inevitable in any (single-server) aPAKE protocol. It can be avoided in
|
||
the case of OPAQUE by resorting to a multi-server threshold OPRF implementation,
|
||
e.g., <span>[<a href="#TOPPSS" class="cite xref">TOPPSS</a>]</span>. Furthermore, if the server does not
|
||
sample the PRF <code>seed</code> with sufficiently high entropy, or if it is not kept hidden from an
|
||
adversary, then any derivatives from the client's password may also be susceptible to an
|
||
offline dictionary attack to recover the original password.<a href="#section-10.11-1" class="pilcrow">¶</a></p>
|
||
<p id="section-10.11-2">Some applications may require learning the client's password to enforce password
|
||
rules. Doing so invalidates this important security property of OPAQUE and is
|
||
<span class="bcp14">NOT RECOMMENDED</span> unless it is not possible for applications to move such checks
|
||
to the client. Note that limited checks at the server are possible to implement, e.g.,
|
||
detecting repeated passwords upon reregistrations or password change.<a href="#section-10.11-2" class="pilcrow">¶</a></p>
|
||
<p id="section-10.11-3">In general, passwords should be selected with sufficient entropy to avoid being susceptible
|
||
to recovery through dictionary attacks, both online and offline.<a href="#section-10.11-3" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="ake-private-key-storage">
|
||
<section id="section-10.12">
|
||
<h3 id="name-ake-private-key-storage">
|
||
<a href="#section-10.12" class="section-number selfRef">10.12. </a><a href="#name-ake-private-key-storage" class="section-name selfRef">AKE Private Key Storage</a>
|
||
</h3>
|
||
<p id="section-10.12-1">Server implementations of OPAQUE do not need access to the raw AKE private key. They only require
|
||
the ability to compute shared secrets as specified in <a href="#key-schedule-functions" class="auto internal xref">Section 6.4.2</a>. Thus, applications
|
||
may store the server AKE private key in a Hardware Security Module (HSM) or
|
||
similar. Upon compromise of <code>oprf_seed</code> and client envelopes, this would prevent an
|
||
attacker from using this data to mount a server spoofing attack. Supporting implementations
|
||
need to consider allowing separate AKE and OPRF algorithms in cases where the HSM is
|
||
incompatible with the OPRF algorithm.<a href="#section-10.12-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="client-authentication-using-credentials">
|
||
<section id="section-10.13">
|
||
<h3 id="name-client-authentication-using">
|
||
<a href="#section-10.13" class="section-number selfRef">10.13. </a><a href="#name-client-authentication-using" class="section-name selfRef">Client Authentication Using Credentials</a>
|
||
</h3>
|
||
<p id="section-10.13-1">For scenarios in which the client has access to private state that can be persisted across
|
||
registration and login, the client can back up the <code>randomized_password</code> variable (as
|
||
computed in <a href="#finalize-request" class="auto internal xref">Section 5.2.3</a>) so that upon a future login attempt, the client can
|
||
authenticate to the server using <code>randomized_password</code> instead of the original password.
|
||
This can be achieved by supplying an arbitrary password as input to
|
||
<code>CreateCredentialRequest</code> in the login phase, and then using <code>randomized_password</code> from
|
||
the backup in <code>RecoverCredentials</code> (invoked by <code>GenerateKE3</code>) rather than computing it from
|
||
the password.<a href="#section-10.13-1" class="pilcrow">¶</a></p>
|
||
<p id="section-10.13-2">This provides an advantage over the regular authentication flow for login
|
||
in that if <code>randomized_password</code> is compromised, an adversary cannot use this value to
|
||
successfully impersonate the server to the client during login. The drawback is that it is
|
||
only applicable to settings where <code>randomized_password</code> can be treated as a credential
|
||
that can be stored securely after registration and retrieved upon login.<a href="#section-10.13-2" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="iana-considerations">
|
||
<section id="section-11">
|
||
<h2 id="name-iana-considerations">
|
||
<a href="#section-11" class="section-number selfRef">11. </a><a href="#name-iana-considerations" class="section-name selfRef">IANA Considerations</a>
|
||
</h2>
|
||
<p id="section-11-1">This document has no IANA actions.<a href="#section-11-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="sec-combined-references">
|
||
<section id="section-12">
|
||
<h2 id="name-references">
|
||
<a href="#section-12" class="section-number selfRef">12. </a><a href="#name-references" class="section-name selfRef">References</a>
|
||
</h2>
|
||
<div id="sec-normative-references">
|
||
<section id="section-12.1">
|
||
<h3 id="name-normative-references">
|
||
<a href="#section-12.1" class="section-number selfRef">12.1. </a><a href="#name-normative-references" class="section-name selfRef">Normative References</a>
|
||
</h3>
|
||
<dl class="references">
|
||
<dt id="RFC2104">[RFC2104]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Krawczyk, H.</span>, <span class="refAuthor">Bellare, M.</span>, and <span class="refAuthor">R. Canetti</span>, <span class="refTitle">"HMAC: Keyed-Hashing for Message Authentication"</span>, <span class="seriesInfo">RFC 2104</span>, <span class="seriesInfo">DOI 10.17487/RFC2104</span>, <time datetime="1997-02" class="refDate">February 1997</time>, <span><<a href="https://www.rfc-editor.org/info/rfc2104">https://www.rfc-editor.org/info/rfc2104</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC2119">[RFC2119]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Bradner, S.</span>, <span class="refTitle">"Key words for use in RFCs to Indicate Requirement Levels"</span>, <span class="seriesInfo">BCP 14</span>, <span class="seriesInfo">RFC 2119</span>, <span class="seriesInfo">DOI 10.17487/RFC2119</span>, <time datetime="1997-03" class="refDate">March 1997</time>, <span><<a href="https://www.rfc-editor.org/info/rfc2119">https://www.rfc-editor.org/info/rfc2119</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC4086">[RFC4086]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Eastlake 3rd, D.</span>, <span class="refAuthor">Schiller, J.</span>, and <span class="refAuthor">S. Crocker</span>, <span class="refTitle">"Randomness Requirements for Security"</span>, <span class="seriesInfo">BCP 106</span>, <span class="seriesInfo">RFC 4086</span>, <span class="seriesInfo">DOI 10.17487/RFC4086</span>, <time datetime="2005-06" class="refDate">June 2005</time>, <span><<a href="https://www.rfc-editor.org/info/rfc4086">https://www.rfc-editor.org/info/rfc4086</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC8174">[RFC8174]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Leiba, B.</span>, <span class="refTitle">"Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words"</span>, <span class="seriesInfo">BCP 14</span>, <span class="seriesInfo">RFC 8174</span>, <span class="seriesInfo">DOI 10.17487/RFC8174</span>, <time datetime="2017-05" class="refDate">May 2017</time>, <span><<a href="https://www.rfc-editor.org/info/rfc8174">https://www.rfc-editor.org/info/rfc8174</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC9497">[RFC9497]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Davidson, A.</span>, <span class="refAuthor">Faz-Hernandez, A.</span>, <span class="refAuthor">Sullivan, N.</span>, and <span class="refAuthor">C. A. Wood</span>, <span class="refTitle">"Oblivious Pseudorandom Functions (OPRFs) Using Prime-Order Groups"</span>, <span class="seriesInfo">RFC 9497</span>, <span class="seriesInfo">DOI 10.17487/RFC9497</span>, <time datetime="2023-12" class="refDate">December 2023</time>, <span><<a href="https://www.rfc-editor.org/info/rfc9497">https://www.rfc-editor.org/info/rfc9497</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
<div id="sec-informative-references">
|
||
<section id="section-12.2">
|
||
<h3 id="name-informative-references">
|
||
<a href="#section-12.2" class="section-number selfRef">12.2. </a><a href="#name-informative-references" class="section-name selfRef">Informative References</a>
|
||
</h3>
|
||
<dl class="references">
|
||
<dt id="BG04">[BG04]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Brown, D.</span> and <span class="refAuthor">R. Galant</span>, <span class="refTitle">"The Static Diffie-Hellman Problem"</span>, <span class="refContent">Cryptology ePrint Archive, Paper 2004/306</span>, <time datetime="2004" class="refDate">2004</time>, <span><<a href="https://eprint.iacr.org/2004/306">https://eprint.iacr.org/2004/306</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="Boyen09">[Boyen09]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Boyen, X.</span>, <span class="refTitle">"HPAKE: Password Authentication Secure against Cross-Site User Impersonation"</span>, <span class="refContent">Cryptology and Network Security (CANS 2009), Lecture Notes in Computer Science, vol. 5888, pp. 279-298</span>, <span class="seriesInfo">DOI 10.1007/978-3-642-10433-6_19</span>, <time datetime="2009" class="refDate">2009</time>, <span><<a href="https://doi.org/10.1007/978-3-642-10433-6_19">https://doi.org/10.1007/978-3-642-10433-6_19</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="Canetti01">[Canetti01]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Canetti, R.</span>, <span class="refTitle">"Universally composable security: A new paradigm for cryptographic protocols"</span>, <span class="refContent">42nd IEEE Symposium on Foundations of Computer Science, pp. 136-145</span>, <span class="seriesInfo">DOI 10.1109/SFCS.2001.959888</span>, <time datetime="2001" class="refDate">2001</time>, <span><<a href="https://doi.org/10.1109/SFCS.2001.959888">https://doi.org/10.1109/SFCS.2001.959888</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="Cheon06">[Cheon06]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Cheon, J. H.</span>, <span class="refTitle">"Security Analysis of the Strong Diffie-Hellman Problem"</span>, <span class="refContent">Advances in Cryptology - EUROCRYPT 2006, Lecture Notes in Computer Science, vol. 4004, pp. 1-11</span>, <span class="seriesInfo">DOI 10.1007/11761679_1</span>, <time datetime="2006" class="refDate">2006</time>, <span><<a href="https://doi.org/10.1007/11761679_1">https://doi.org/10.1007/11761679_1</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="DL24">[DL24]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Dayanikli, D.</span> and <span class="refAuthor">A. Lehmann</span>, <span class="refTitle">"(Strong) aPAKE Revisited: Capturing Multi-User Security and Salting"</span>, <span class="refContent">Cryptology ePrint Archive, Paper 2024/756</span>, <time datetime="2024" class="refDate">2024</time>, <span><<a href="https://eprint.iacr.org/2024/756">https://eprint.iacr.org/2024/756</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="FIPS202">[FIPS202]</dt>
|
||
<dd>
|
||
<span class="refAuthor">NIST</span>, <span class="refTitle">"SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions"</span>, <span class="seriesInfo">NIST FIPS 202</span>, <span class="seriesInfo">DOI 10.6028/NIST.FIPS.202</span>, <time datetime="2015-08" class="refDate">August 2015</time>, <span><<a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf">https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="FK00">[FK00]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Ford, W.</span> and <span class="refAuthor">B. S. Kaliski, Jr</span>, <span class="refTitle">"Server-assisted generation of a strong secret from a password"</span>, <span class="refContent">IEEE 9th International Workshops on Enabling Technologies: Infrastructure for Collaborative Enterprises (WET ICE 2000), pp. 176-180</span>, <span class="seriesInfo">DOI 10.1109/ENABL.2000.883724</span>, <time datetime="2000" class="refDate">2000</time>, <span><<a href="https://doi.org/10.1109/ENABL.2000.883724">https://doi.org/10.1109/ENABL.2000.883724</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="HJKW23">[HJKW23]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Hesse, J.</span>, <span class="refAuthor">Jarecki, S.</span>, <span class="refAuthor">Krawczyk, H.</span>, and <span class="refAuthor">C. Wood</span>, <span class="refTitle">"Password-Authenticated TLS via OPAQUE and Post-Handshake Authentication"</span>, <span class="refContent">Advances in Cryptology - EUROCRYPT 2023, Lecture Notes in Computer Science, vol. 14008, pp. 98-127</span>, <span class="seriesInfo">DOI 10.1007/978-3-031-30589-4_4</span>, <time datetime="2023" class="refDate">2023</time>, <span><<a href="https://doi.org/10.1007/978-3-031-30589-4_4">https://doi.org/10.1007/978-3-031-30589-4_4</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="HMQV">[HMQV]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Krawczyk, H.</span>, <span class="refTitle">"HMQV: A High-Performance Secure Diffie-Hellman Protocol"</span>, <span class="refContent">Cryptology ePrint Archive, Paper 2005/176</span>, <time datetime="2005" class="refDate">2005</time>, <span><<a href="https://eprint.iacr.org/2005/176">https://eprint.iacr.org/2005/176</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="JKKX16">[JKKX16]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Jarecki, S.</span>, <span class="refAuthor">Kiayias, A.</span>, <span class="refAuthor">Krawczyk, H.</span>, and <span class="refAuthor">J. Xu</span>, <span class="refTitle">"Highly-Efficient and Composable Password-Protected Secret Sharing (Or: How to Protect Your Bitcoin Wallet Online)"</span>, <span class="refContent">2016 IEEE European Symposium on Security and Privacy (EuroS&P), pp. 276-291</span>, <span class="seriesInfo">DOI 10.1109/EuroSP.2016.30</span>, <time datetime="2016" class="refDate">2016</time>, <span><<a href="https://doi.org/10.1109/EuroSP.2016.30">https://doi.org/10.1109/EuroSP.2016.30</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="JKX18">[JKX18]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Jarecki, S.</span>, <span class="refAuthor">Krawczyk, H.</span>, and <span class="refAuthor">J. Xu</span>, <span class="refTitle">"OPAQUE: An Asymmetric PAKE Protocol Secure Against Pre-Computation Attacks"</span>, <span class="refContent">Cryptology ePrint Archive, Paper 2018/163</span>, <time datetime="2018" class="refDate">2018</time>, <span><<a href="https://eprint.iacr.org/2018/163">https://eprint.iacr.org/2018/163</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="keyagreement">[keyagreement]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Barker, E.</span>, <span class="refAuthor">Chen, L.</span>, <span class="refAuthor">Roginsky, A.</span>, <span class="refAuthor">Vassilev, A.</span>, and <span class="refAuthor">R. Davis</span>, <span class="refTitle">"Recommendation for Pair-Wise Key-Establishment Schemes Using Discrete Logarithm Cryptography"</span>, <span class="seriesInfo">DOI 10.6028/nist.sp.800-56ar3</span>, <span class="seriesInfo">NIST SP 800-56Ar3</span>, <time datetime="2018-04" class="refDate">April 2018</time>, <span><<a href="https://doi.org/10.6028/nist.sp.800-56ar3">https://doi.org/10.6028/nist.sp.800-56ar3</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="I-D.krawczyk-cfrg-opaque">[Krawczyk20]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Krawczyk, H.</span>, <span class="refTitle">"The OPAQUE Asymmetric PAKE Protocol"</span>, <span class="refContent">Work in Progress</span>, <span class="seriesInfo">Internet-Draft, draft-krawczyk-cfrg-opaque-06</span>, <time datetime="2020-06-19" class="refDate">19 June 2020</time>, <span><<a href="https://datatracker.ietf.org/doc/html/draft-krawczyk-cfrg-opaque-06">https://datatracker.ietf.org/doc/html/draft-krawczyk-cfrg-opaque-06</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="LGR20">[LGR20]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Len, J.</span>, <span class="refAuthor">Grubbs, P.</span>, and <span class="refAuthor">T. Ristenpart</span>, <span class="refTitle">"Partitioning Oracle Attacks"</span>, <span class="refContent">Cryptology ePrint Archive, Paper 2020/1491</span>, <time datetime="2021" class="refDate">2021</time>, <span><<a href="https://eprint.iacr.org/2020/1491.pdf">https://eprint.iacr.org/2020/1491.pdf</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="NISTCurves">[NISTCurves]</dt>
|
||
<dd>
|
||
<span class="refAuthor">NIST</span>, <span class="refTitle">"Digital Signature Standard (DSS)"</span>, <span class="seriesInfo">NIST FIPS 186-5</span>, <span class="seriesInfo">DOI 10.6028/nist.fips.186-5</span>, <time datetime="2013" class="refDate">2013</time>, <span><<a href="https://doi.org/10.6028/nist.fips.186-5">https://doi.org/10.6028/nist.fips.186-5</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC5869">[RFC5869]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Krawczyk, H.</span> and <span class="refAuthor">P. Eronen</span>, <span class="refTitle">"HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"</span>, <span class="seriesInfo">RFC 5869</span>, <span class="seriesInfo">DOI 10.17487/RFC5869</span>, <time datetime="2010-05" class="refDate">May 2010</time>, <span><<a href="https://www.rfc-editor.org/info/rfc5869">https://www.rfc-editor.org/info/rfc5869</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC7748">[RFC7748]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Langley, A.</span>, <span class="refAuthor">Hamburg, M.</span>, and <span class="refAuthor">S. Turner</span>, <span class="refTitle">"Elliptic Curves for Security"</span>, <span class="seriesInfo">RFC 7748</span>, <span class="seriesInfo">DOI 10.17487/RFC7748</span>, <time datetime="2016-01" class="refDate">January 2016</time>, <span><<a href="https://www.rfc-editor.org/info/rfc7748">https://www.rfc-editor.org/info/rfc7748</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC7914">[RFC7914]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Percival, C.</span> and <span class="refAuthor">S. Josefsson</span>, <span class="refTitle">"The scrypt Password-Based Key Derivation Function"</span>, <span class="seriesInfo">RFC 7914</span>, <span class="seriesInfo">DOI 10.17487/RFC7914</span>, <time datetime="2016-08" class="refDate">August 2016</time>, <span><<a href="https://www.rfc-editor.org/info/rfc7914">https://www.rfc-editor.org/info/rfc7914</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC8017">[RFC8017]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Moriarty, K., Ed.</span>, <span class="refAuthor">Kaliski, B.</span>, <span class="refAuthor">Jonsson, J.</span>, and <span class="refAuthor">A. Rusch</span>, <span class="refTitle">"PKCS #1: RSA Cryptography Specifications Version 2.2"</span>, <span class="seriesInfo">RFC 8017</span>, <span class="seriesInfo">DOI 10.17487/RFC8017</span>, <time datetime="2016-11" class="refDate">November 2016</time>, <span><<a href="https://www.rfc-editor.org/info/rfc8017">https://www.rfc-editor.org/info/rfc8017</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC8018">[RFC8018]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Moriarty, K., Ed.</span>, <span class="refAuthor">Kaliski, B.</span>, and <span class="refAuthor">A. Rusch</span>, <span class="refTitle">"PKCS #5: Password-Based Cryptography Specification Version 2.1"</span>, <span class="seriesInfo">RFC 8018</span>, <span class="seriesInfo">DOI 10.17487/RFC8018</span>, <time datetime="2017-01" class="refDate">January 2017</time>, <span><<a href="https://www.rfc-editor.org/info/rfc8018">https://www.rfc-editor.org/info/rfc8018</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC8125">[RFC8125]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Schmidt, J.</span>, <span class="refTitle">"Requirements for Password-Authenticated Key Agreement (PAKE) Schemes"</span>, <span class="seriesInfo">RFC 8125</span>, <span class="seriesInfo">DOI 10.17487/RFC8125</span>, <time datetime="2017-04" class="refDate">April 2017</time>, <span><<a href="https://www.rfc-editor.org/info/rfc8125">https://www.rfc-editor.org/info/rfc8125</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC8446">[RFC8446]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Rescorla, E.</span>, <span class="refTitle">"The Transport Layer Security (TLS) Protocol Version 1.3"</span>, <span class="seriesInfo">RFC 8446</span>, <span class="seriesInfo">DOI 10.17487/RFC8446</span>, <time datetime="2018-08" class="refDate">August 2018</time>, <span><<a href="https://www.rfc-editor.org/info/rfc8446">https://www.rfc-editor.org/info/rfc8446</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC9106">[RFC9106]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Biryukov, A.</span>, <span class="refAuthor">Dinu, D.</span>, <span class="refAuthor">Khovratovich, D.</span>, and <span class="refAuthor">S. Josefsson</span>, <span class="refTitle">"Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications"</span>, <span class="seriesInfo">RFC 9106</span>, <span class="seriesInfo">DOI 10.17487/RFC9106</span>, <time datetime="2021-09" class="refDate">September 2021</time>, <span><<a href="https://www.rfc-editor.org/info/rfc9106">https://www.rfc-editor.org/info/rfc9106</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC9180">[RFC9180]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Barnes, R.</span>, <span class="refAuthor">Bhargavan, K.</span>, <span class="refAuthor">Lipp, B.</span>, and <span class="refAuthor">C. Wood</span>, <span class="refTitle">"Hybrid Public Key Encryption"</span>, <span class="seriesInfo">RFC 9180</span>, <span class="seriesInfo">DOI 10.17487/RFC9180</span>, <time datetime="2022-02" class="refDate">February 2022</time>, <span><<a href="https://www.rfc-editor.org/info/rfc9180">https://www.rfc-editor.org/info/rfc9180</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC9380">[RFC9380]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Faz-Hernandez, A.</span>, <span class="refAuthor">Scott, S.</span>, <span class="refAuthor">Sullivan, N.</span>, <span class="refAuthor">Wahby, R. S.</span>, and <span class="refAuthor">C. A. Wood</span>, <span class="refTitle">"Hashing to Elliptic Curves"</span>, <span class="seriesInfo">RFC 9380</span>, <span class="seriesInfo">DOI 10.17487/RFC9380</span>, <time datetime="2023-08" class="refDate">August 2023</time>, <span><<a href="https://www.rfc-editor.org/info/rfc9380">https://www.rfc-editor.org/info/rfc9380</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="RFC9496">[RFC9496]</dt>
|
||
<dd>
|
||
<span class="refAuthor">de Valence, H.</span>, <span class="refAuthor">Grigg, J.</span>, <span class="refAuthor">Hamburg, M.</span>, <span class="refAuthor">Lovecruft, I.</span>, <span class="refAuthor">Tankersley, G.</span>, and <span class="refAuthor">F. Valsorda</span>, <span class="refTitle">"The ristretto255 and decaf448 Groups"</span>, <span class="seriesInfo">RFC 9496</span>, <span class="seriesInfo">DOI 10.17487/RFC9496</span>, <time datetime="2023-12" class="refDate">December 2023</time>, <span><<a href="https://www.rfc-editor.org/info/rfc9496">https://www.rfc-editor.org/info/rfc9496</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="SIGMA-I">[SIGMA-I]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Krawczyk, H.</span>, <span class="refTitle">"SIGMA: The 'SIGn-and-MAc' Approach to Authenticated Diffie-Hellman and its Use in the IKE Protocols"</span>, <time datetime="2003" class="refDate">2003</time>, <span><<a href="https://www.iacr.org/cryptodb/archive/2003/CRYPTO/1495/1495.pdf">https://www.iacr.org/cryptodb/archive/2003/CRYPTO/1495/1495.pdf</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="TOPPSS">[TOPPSS]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Jarecki, S.</span>, <span class="refAuthor">Kiayias, A.</span>, <span class="refAuthor">Krawczyk, H.</span>, and <span class="refAuthor">J. Xu</span>, <span class="refTitle">"TOPPSS: Cost-Minimal Password-Protected Secret Sharing based on Threshold OPRF"</span>, <span class="refContent">Applied Cryptology and Network Security - ACNS 2017, Lecture Notes in Computer Science, vol. 10355, pp. 39-58</span>, <span class="seriesInfo">DOI 10.1007/978-3-319-61204-1_3</span>, <time datetime="2017" class="refDate">2017</time>, <span><<a href="https://doi.org/10.1007/978-3-319-61204-1_3">https://doi.org/10.1007/978-3-319-61204-1_3</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="TripleDH">[TripleDH]</dt>
|
||
<dd>
|
||
<span class="refAuthor">Marlinspike, M.</span>, <span class="refTitle">"Simplifying OTR deniability"</span>, <span class="refContent">Signal Blog</span>, <time datetime="2013-07-27" class="refDate">27 July 2013</time>, <span><<a href="https://signal.org/blog/simplifying-otr-deniability">https://signal.org/blog/simplifying-otr-deniability</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
<dt id="WhatsAppE2E">[WhatsAppE2E]</dt>
|
||
<dd>
|
||
<span class="refAuthor">WhatsApp</span>, <span class="refTitle">"Security of End-to-End Encrypted Backups"</span>, <span class="refContent">WhatsApp Security Whitepaper</span>, <time datetime="2021-09-10" class="refDate">10 September 2021</time>, <span><<a href="https://www.whatsapp.com/security/WhatsApp_Security_Encrypted_Backups_Whitepaper.pdf">https://www.whatsapp.com/security/WhatsApp_Security_Encrypted_Backups_Whitepaper.pdf</a>></span>. </dd>
|
||
<dd class="break"></dd>
|
||
</dl>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="alternate-key-recovery">
|
||
<section id="appendix-A">
|
||
<h2 id="name-alternate-key-recovery-mech">
|
||
<a href="#appendix-A" class="section-number selfRef">Appendix A. </a><a href="#name-alternate-key-recovery-mech" class="section-name selfRef">Alternate Key Recovery Mechanisms</a>
|
||
</h2>
|
||
<p id="appendix-A-1">Client authentication material can be stored and retrieved using different key
|
||
recovery mechanisms. Any key recovery mechanism that encrypts data
|
||
in the envelope <span class="bcp14">MUST</span> use an authenticated encryption scheme with random
|
||
key-robustness (or key-committing). Deviating from the key-robustness
|
||
requirement may open the protocol to attacks, e.g., <span>[<a href="#LGR20" class="cite xref">LGR20</a>]</span>.
|
||
This specification enforces this property by using a MAC over the envelope
|
||
contents.<a href="#appendix-A-1" class="pilcrow">¶</a></p>
|
||
<p id="appendix-A-2">We remark that <code>export_key</code> for authentication or encryption requires
|
||
no special properties from the authentication or encryption schemes
|
||
as long as <code>export_key</code> is used only after authentication material is successfully
|
||
recovered, i.e., after the MAC in <code>RecoverCredentials</code> passes verification.<a href="#appendix-A-2" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="alternate-akes">
|
||
<section id="appendix-B">
|
||
<h2 id="name-alternate-ake-instantiation">
|
||
<a href="#appendix-B" class="section-number selfRef">Appendix B. </a><a href="#name-alternate-ake-instantiation" class="section-name selfRef">Alternate AKE Instantiations</a>
|
||
</h2>
|
||
<p id="appendix-B-1">It is possible to instantiate OPAQUE with other AKEs, such as HMQV <span>[<a href="#HMQV" class="cite xref">HMQV</a>]</span> and SIGMA-I <span>[<a href="#SIGMA-I" class="cite xref">SIGMA-I</a>]</span>.
|
||
HMQV is similar to 3DH but varies in its key schedule. SIGMA-I uses digital signatures
|
||
rather than static DH keys for authentication. Specification of these instantiations is
|
||
left to future documents. A sketch of how these instantiations might change is included
|
||
in the next subsection for posterity.<a href="#appendix-B-1" class="pilcrow">¶</a></p>
|
||
<p id="appendix-B-2">OPAQUE may also be instantiated with any post-quantum (PQ) AKE protocol that has the message
|
||
flow above and security properties (KCI resistance and forward secrecy) outlined
|
||
in <a href="#security-considerations" class="auto internal xref">Section 10</a>. Note that such an instantiation is not quantum-safe unless
|
||
the OPRF is quantum-safe. However, an OPAQUE instantiation where the AKE protocol is quantum-safe,
|
||
but the OPRF is not, would still ensure the confidentiality and integrity of application data encrypted
|
||
under <code>session_key</code> (or a key derived from it) with a quantum-safe encryption function.
|
||
However, the only effect of a break of the OPRF by a future quantum attacker would be
|
||
the ability of this attacker to run at that time an exhaustive dictionary
|
||
attack against the old user's password and only for users whose envelopes were
|
||
harvested while in use (in the case of OPAQUE run over a TLS channel with the
|
||
server, harvesting such envelopes requires targeted active attacks).<a href="#appendix-B-2" class="pilcrow">¶</a></p>
|
||
<div id="hmqv-sketch">
|
||
<section id="appendix-B.1">
|
||
<h3 id="name-hmqv-instantiation-sketch">
|
||
<a href="#appendix-B.1" class="section-number selfRef">B.1. </a><a href="#name-hmqv-instantiation-sketch" class="section-name selfRef">HMQV Instantiation Sketch</a>
|
||
</h3>
|
||
<p id="appendix-B.1-1">An HMQV instantiation would work similarly to OPAQUE-3DH, differing primarily in the key
|
||
schedule <span>[<a href="#HMQV" class="cite xref">HMQV</a>]</span>. First, the key schedule <code>preamble</code> value would use a different constant prefix
|
||
-- "HMQV" instead of "3DH" -- as shown below.<a href="#appendix-B.1-1" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="appendix-B.1-2">
|
||
<pre>
|
||
preamble = concat("HMQV",
|
||
I2OSP(len(client_identity), 2), client_identity,
|
||
KE1,
|
||
I2OSP(len(server_identity), 2), server_identity,
|
||
KE2.credential_response,
|
||
KE2.auth_response.server_nonce,
|
||
KE2.auth_response.server_public_keyshare)
|
||
</pre><a href="#appendix-B.1-2" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="appendix-B.1-3">Second, the <code>IKM</code> derivation would change. Assuming HMQV is instantiated with a cyclic
|
||
group of prime order p with bit length L, clients would compute <code>IKM</code> as follows:<a href="#appendix-B.1-3" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="appendix-B.1-4">
|
||
<pre>
|
||
u' = (eskU + u \* skU) mod p
|
||
IKM = (epkS \* pkS^s)^u'
|
||
</pre><a href="#appendix-B.1-4" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="appendix-B.1-5">Likewise, servers would compute <code>IKM</code> as follows:<a href="#appendix-B.1-5" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="appendix-B.1-6">
|
||
<pre>
|
||
s' = (eskS + s \* skS) mod p
|
||
IKM = (epkU \* pkU^u)^s'
|
||
</pre><a href="#appendix-B.1-6" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="appendix-B.1-7">In both cases, <code>u</code> would be computed as follows:<a href="#appendix-B.1-7" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="appendix-B.1-8">
|
||
<pre>
|
||
hashInput = concat(I2OSP(len(epkU), 2), epkU,
|
||
I2OSP(len(info), 2), info,
|
||
I2OSP(len("client"), 2), "client")
|
||
u = Hash(hashInput) mod L
|
||
</pre><a href="#appendix-B.1-8" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="appendix-B.1-9">Likewise, <code>s</code> would be computed as follows:<a href="#appendix-B.1-9" class="pilcrow">¶</a></p>
|
||
<div class="sourcecode" id="appendix-B.1-10">
|
||
<pre>
|
||
hashInput = concat(I2OSP(len(epkS), 2), epkS,
|
||
I2OSP(len(info), 2), info,
|
||
I2OSP(len("server"), 2), "server")
|
||
s = Hash(hashInput) mod L
|
||
</pre><a href="#appendix-B.1-10" class="pilcrow">¶</a>
|
||
</div>
|
||
<p id="appendix-B.1-11">Hash is the same hash function used in the main OPAQUE protocol for key derivation.
|
||
Its output length (in bits) must be at least L.<a href="#appendix-B.1-11" class="pilcrow">¶</a></p>
|
||
<p id="appendix-B.1-12">Both parties should perform validation (as in <a href="#validation" class="auto internal xref">Section 10.7</a>) on each other's
|
||
public keys before computing the above parameters.<a href="#appendix-B.1-12" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="sigma-i-instantiation-sketch">
|
||
<section id="appendix-B.2">
|
||
<h3 id="name-sigma-i-instantiation-sketc">
|
||
<a href="#appendix-B.2" class="section-number selfRef">B.2. </a><a href="#name-sigma-i-instantiation-sketc" class="section-name selfRef">SIGMA-I Instantiation Sketch</a>
|
||
</h3>
|
||
<p id="appendix-B.2-1">A SIGMA-I <span>[<a href="#SIGMA-I" class="cite xref">SIGMA-I</a>]</span> instantiation differs more drastically from OPAQUE-3DH since authentication
|
||
uses digital signatures instead of Diffie-Hellman. In particular, both <code>KE2</code> and <code>KE3</code>
|
||
would carry a digital signature, computed using the server and client private keys
|
||
established during registration, respectively, as well as a MAC, where the MAC is
|
||
computed as in OPAQUE-3DH but it also covers the identity of the sender.<a href="#appendix-B.2-1" class="pilcrow">¶</a></p>
|
||
<p id="appendix-B.2-2">The key schedule would also change. Specifically, the key schedule <code>preamble</code> value would
|
||
use a different constant prefix -- "SIGMA-I" instead of "3DH" -- and the <code>IKM</code> computation
|
||
would use only the ephemeral public keys exchanged between client and server.<a href="#appendix-B.2-2" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="test-vectors">
|
||
<section id="appendix-C">
|
||
<h2 id="name-test-vectors">
|
||
<a href="#appendix-C" class="section-number selfRef">Appendix C. </a><a href="#name-test-vectors" class="section-name selfRef">Test Vectors</a>
|
||
</h2>
|
||
<p id="appendix-C-1">This section contains real and fake test vectors for the OPAQUE-3DH specification.
|
||
Each real test vector in <a href="#real-vectors" class="auto internal xref">Appendix C.1</a> specifies the configuration information,
|
||
protocol inputs, intermediate values computed during registration and authentication,
|
||
and protocol outputs.<a href="#appendix-C-1" class="pilcrow">¶</a></p>
|
||
<p id="appendix-C-2">Similarly, each fake test vector in <a href="#fake-vectors" class="auto internal xref">Appendix C.2</a> specifies
|
||
the configuration information, protocol inputs, and protocol
|
||
outputs computed during the authentication of an unknown or unregistered user. Note that <code>masking_key</code>,
|
||
<code>client_private_key</code>, and <code>client_public_key</code> are used as additional inputs as described in
|
||
<a href="#create-credential-response" class="auto internal xref">Section 6.3.2.2</a>. <code>client_public_key</code> is used as the fake <code>record</code>'s public key, and
|
||
<code>masking_key</code> is used for the fake <code>record</code>'s masking key parameter.<a href="#appendix-C-2" class="pilcrow">¶</a></p>
|
||
<p id="appendix-C-3">All values are encoded in hexadecimal strings. The configuration information
|
||
includes the (OPRF, Hash, KSF, KDF, MAC, Group, Context) tuple, where the Group
|
||
matches that which is used in the OPRF. The KSF used for each test vector is the
|
||
identity function (denoted Identity), which returns as output the input message
|
||
supplied to the function without any modification, i.e., <code>msg</code> = Stretch(msg).<a href="#appendix-C-3" class="pilcrow">¶</a></p>
|
||
<div id="real-vectors">
|
||
<section id="appendix-C.1">
|
||
<h3 id="name-real-test-vectors">
|
||
<a href="#appendix-C.1" class="section-number selfRef">C.1. </a><a href="#name-real-test-vectors" class="section-name selfRef">Real Test Vectors</a>
|
||
</h3>
|
||
<div id="opaque-3dh-real-test-vector-1">
|
||
<section id="appendix-C.1.1">
|
||
<h4 id="name-opaque-3dh-real-test-vector">
|
||
<a href="#appendix-C.1.1" class="section-number selfRef">C.1.1. </a><a href="#name-opaque-3dh-real-test-vector" class="section-name selfRef">OPAQUE-3DH Real Test Vector 1</a>
|
||
</h4>
|
||
<div id="configuration">
|
||
<section id="appendix-C.1.1.1">
|
||
<h5 id="name-configuration">
|
||
<a href="#appendix-C.1.1.1" class="section-number selfRef">C.1.1.1. </a><a href="#name-configuration" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.1.1-1">
|
||
<pre>
|
||
OPRF: ristretto255-SHA512
|
||
Hash: SHA512
|
||
KSF: Identity
|
||
KDF: HKDF-SHA512
|
||
MAC: HMAC-SHA512
|
||
Group: ristretto255
|
||
Context: 4f50415155452d504f43
|
||
Nh: 64
|
||
Npk: 32
|
||
Nsk: 32
|
||
Nm: 64
|
||
Nx: 64
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.1.1.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values">
|
||
<section id="appendix-C.1.1.2">
|
||
<h5 id="name-input-values">
|
||
<a href="#appendix-C.1.1.2" class="section-number selfRef">C.1.1.2. </a><a href="#name-input-values" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.1.2-1">
|
||
<pre>
|
||
oprf_seed: f433d0227b0b9dd54f7c4422b600e764e47fb503f1f9a0f0a47c6606b0
|
||
54a7fdc65347f1a08f277e22358bbabe26f823fca82c7848e9a75661f4ec5d5c1989e
|
||
f
|
||
credential_identifier: 31323334
|
||
password: 436f7272656374486f72736542617474657279537461706c65
|
||
envelope_nonce: ac13171b2f17bc2c74997f0fce1e1f35bec6b91fe2e12dbd323d2
|
||
3ba7a38dfec
|
||
masking_nonce: 38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80
|
||
f612fdfc6d
|
||
server_private_key: 47451a85372f8b3537e249d7b54188091fb18edde78094b43
|
||
e2ba42b5eb89f0d
|
||
server_public_key: b2fe7af9f48cc502d016729d2fe25cdd433f2c4bc904660b2a
|
||
382c9b79df1a78
|
||
server_nonce: 71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e
|
||
138e3d4a1
|
||
client_nonce: da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb38
|
||
0cae6a6cc
|
||
client_keyshare_seed: 82850a697b42a505f5b68fcdafce8c31f0af2b581f063cf
|
||
1091933541936304b
|
||
server_keyshare_seed: 05a4f54206eef1ba2f615bc0aa285cb22f26d1153b5b40a
|
||
1e85ff80da12f982f
|
||
blind_registration: 76cfbfe758db884bebb33582331ba9f159720ca8784a2a070
|
||
a265d9c2d6abe01
|
||
blind_login: 6ecc102d2e7a7cf49617aad7bbe188556792d4acd60a1a8a8d2b65d4
|
||
b0790308
|
||
</pre><a href="#appendix-C.1.1.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="intermediate-values">
|
||
<section id="appendix-C.1.1.3">
|
||
<h5 id="name-intermediate-values">
|
||
<a href="#appendix-C.1.1.3" class="section-number selfRef">C.1.1.3. </a><a href="#name-intermediate-values" class="section-name selfRef">Intermediate Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.1.3-1">
|
||
<pre>
|
||
client_public_key: 76a845464c68a5d2f7e442436bb1424953b17d3e2e289ccbac
|
||
cafb57ac5c3675
|
||
auth_key: 6cd32316f18d72a9a927a83199fa030663a38ce0c11fbaef82aa9003773
|
||
0494fc555c4d49506284516edd1628c27965b7555a4ebfed2223199f6c67966dde822
|
||
randomized_password: aac48c25ab036e30750839d31d6e73007344cb1155289fb7
|
||
d329beb932e9adeea73d5d5c22a0ce1952f8aba6d66007615cd1698d4ac85ef1fcf15
|
||
0031d1435d9
|
||
envelope: ac13171b2f17bc2c74997f0fce1e1f35bec6b91fe2e12dbd323d23ba7a3
|
||
8dfec634b0f5b96109c198a8027da51854c35bee90d1e1c781806d07d49b76de6a28b
|
||
8d9e9b6c93b9f8b64d16dddd9c5bfb5fea48ee8fd2f75012a8b308605cdd8ba5
|
||
handshake_secret: 81263cb85a0cfa12450f0f388de4e92291ec4c7c7a0878b6245
|
||
50ff528726332f1298fc6cc822a432c89504347c7a2ccd70316ae3da6a15e0399e6db
|
||
3f7c1b12
|
||
server_mac_key: 0d36b26cfe38f51f804f0a9361818f32ee1ce2a4e5578653b5271
|
||
84af058d3b2d8075c296fd84d24677913d1baa109290cd81a13ed383f9091a3804e65
|
||
298dfc
|
||
client_mac_key: 91750adbac54a5e8e53b4c233cc8d369fe83b0de1b6a3cd85575e
|
||
eb0bb01a6a90a086a2cf5fe75fff2a9379c30ba9049510a33b5b0b1444a88800fc3ee
|
||
e2260d
|
||
oprf_key: 5d4c6a8b7c7138182afb4345d1fae6a9f18a1744afbcc3854f8f5a2b4b4
|
||
c6d05
|
||
</pre><a href="#appendix-C.1.1.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values">
|
||
<section id="appendix-C.1.1.4">
|
||
<h5 id="name-output-values">
|
||
<a href="#appendix-C.1.1.4" class="section-number selfRef">C.1.1.4. </a><a href="#name-output-values" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.1.4-1">
|
||
<pre>
|
||
registration_request: 5059ff249eb1551b7ce4991f3336205bde44a105a032e74
|
||
7d21bf382e75f7a71
|
||
registration_response: 7408a268083e03abc7097fc05b587834539065e86fb0c7
|
||
b6342fcf5e01e5b019b2fe7af9f48cc502d016729d2fe25cdd433f2c4bc904660b2a3
|
||
82c9b79df1a78
|
||
registration_upload: 76a845464c68a5d2f7e442436bb1424953b17d3e2e289ccb
|
||
accafb57ac5c36751ac5844383c7708077dea41cbefe2fa15724f449e535dd7dd562e
|
||
66f5ecfb95864eadddec9db5874959905117dad40a4524111849799281fefe3c51fa8
|
||
2785c5ac13171b2f17bc2c74997f0fce1e1f35bec6b91fe2e12dbd323d23ba7a38dfe
|
||
c634b0f5b96109c198a8027da51854c35bee90d1e1c781806d07d49b76de6a28b8d9e
|
||
9b6c93b9f8b64d16dddd9c5bfb5fea48ee8fd2f75012a8b308605cdd8ba5
|
||
KE1: c4dedb0ba6ed5d965d6f250fbe554cd45cba5dfcce3ce836e4aee778aa3cd44d
|
||
da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb380cae6a6cc6e29b
|
||
ee50701498605b2c085d7b241ca15ba5c32027dd21ba420b94ce60da326
|
||
KE2: 7e308140890bcde30cbcea28b01ea1ecfbd077cff62c4def8efa075aabcbb471
|
||
38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6dd6ec6
|
||
0bcdb26dc455ddf3e718f1020490c192d70dfc7e403981179d8073d1146a4f9aa1ced
|
||
4e4cd984c657eb3b54ced3848326f70331953d91b02535af44d9fedc80188ca46743c
|
||
52786e0382f95ad85c08f6afcd1ccfbff95e2bdeb015b166c6b20b92f832cc6df01e0
|
||
b86a7efd92c1c804ff865781fa93f2f20b446c8371b671cd9960ecef2fe0d0f749498
|
||
6fa3d8b2bb01963537e60efb13981e138e3d4a1c4f62198a9d6fa9170c42c3c71f197
|
||
1b29eb1d5d0bd733e40816c91f7912cc4a660c48dae03e57aaa38f3d0cffcfc21852e
|
||
bc8b405d15bd6744945ba1a93438a162b6111699d98a16bb55b7bdddfe0fc5608b23d
|
||
a246e7bd73b47369169c5c90
|
||
KE3: 4455df4f810ac31a6748835888564b536e6da5d9944dfea9e34defb9575fe5e2
|
||
661ef61d2ae3929bcf57e53d464113d364365eb7d1a57b629707ca48da18e442
|
||
export_key: 1ef15b4fa99e8a852412450ab78713aad30d21fa6966c9b8c9fb3262a
|
||
970dc62950d4dd4ed62598229b1b72794fc0335199d9f7fcc6eaedde92cc04870e63f
|
||
16
|
||
session_key: 42afde6f5aca0cfa5c163763fbad55e73a41db6b41bc87b8e7b62214
|
||
a8eedc6731fa3cb857d657ab9b3764b89a84e91ebcb4785166fbb02cedfcbdfda215b
|
||
96f
|
||
</pre><a href="#appendix-C.1.1.4-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="opaque-3dh-real-test-vector-2">
|
||
<section id="appendix-C.1.2">
|
||
<h4 id="name-opaque-3dh-real-test-vector-">
|
||
<a href="#appendix-C.1.2" class="section-number selfRef">C.1.2. </a><a href="#name-opaque-3dh-real-test-vector-" class="section-name selfRef">OPAQUE-3DH Real Test Vector 2</a>
|
||
</h4>
|
||
<div id="configuration-1">
|
||
<section id="appendix-C.1.2.1">
|
||
<h5 id="name-configuration-2">
|
||
<a href="#appendix-C.1.2.1" class="section-number selfRef">C.1.2.1. </a><a href="#name-configuration-2" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.2.1-1">
|
||
<pre>
|
||
OPRF: ristretto255-SHA512
|
||
Hash: SHA512
|
||
KSF: Identity
|
||
KDF: HKDF-SHA512
|
||
MAC: HMAC-SHA512
|
||
Group: ristretto255
|
||
Context: 4f50415155452d504f43
|
||
Nh: 64
|
||
Npk: 32
|
||
Nsk: 32
|
||
Nm: 64
|
||
Nx: 64
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.1.2.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-1">
|
||
<section id="appendix-C.1.2.2">
|
||
<h5 id="name-input-values-2">
|
||
<a href="#appendix-C.1.2.2" class="section-number selfRef">C.1.2.2. </a><a href="#name-input-values-2" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.2.2-1">
|
||
<pre>
|
||
client_identity: 616c696365
|
||
server_identity: 626f62
|
||
oprf_seed: f433d0227b0b9dd54f7c4422b600e764e47fb503f1f9a0f0a47c6606b0
|
||
54a7fdc65347f1a08f277e22358bbabe26f823fca82c7848e9a75661f4ec5d5c1989e
|
||
f
|
||
credential_identifier: 31323334
|
||
password: 436f7272656374486f72736542617474657279537461706c65
|
||
envelope_nonce: ac13171b2f17bc2c74997f0fce1e1f35bec6b91fe2e12dbd323d2
|
||
3ba7a38dfec
|
||
masking_nonce: 38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80
|
||
f612fdfc6d
|
||
server_private_key: 47451a85372f8b3537e249d7b54188091fb18edde78094b43
|
||
e2ba42b5eb89f0d
|
||
server_public_key: b2fe7af9f48cc502d016729d2fe25cdd433f2c4bc904660b2a
|
||
382c9b79df1a78
|
||
server_nonce: 71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e
|
||
138e3d4a1
|
||
client_nonce: da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb38
|
||
0cae6a6cc
|
||
client_keyshare_seed: 82850a697b42a505f5b68fcdafce8c31f0af2b581f063cf
|
||
1091933541936304b
|
||
server_keyshare_seed: 05a4f54206eef1ba2f615bc0aa285cb22f26d1153b5b40a
|
||
1e85ff80da12f982f
|
||
blind_registration: 76cfbfe758db884bebb33582331ba9f159720ca8784a2a070
|
||
a265d9c2d6abe01
|
||
blind_login: 6ecc102d2e7a7cf49617aad7bbe188556792d4acd60a1a8a8d2b65d4
|
||
b0790308
|
||
</pre><a href="#appendix-C.1.2.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="intermediate-values-1">
|
||
<section id="appendix-C.1.2.3">
|
||
<h5 id="name-intermediate-values-2">
|
||
<a href="#appendix-C.1.2.3" class="section-number selfRef">C.1.2.3. </a><a href="#name-intermediate-values-2" class="section-name selfRef">Intermediate Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.2.3-1">
|
||
<pre>
|
||
client_public_key: 76a845464c68a5d2f7e442436bb1424953b17d3e2e289ccbac
|
||
cafb57ac5c3675
|
||
auth_key: 6cd32316f18d72a9a927a83199fa030663a38ce0c11fbaef82aa9003773
|
||
0494fc555c4d49506284516edd1628c27965b7555a4ebfed2223199f6c67966dde822
|
||
randomized_password: aac48c25ab036e30750839d31d6e73007344cb1155289fb7
|
||
d329beb932e9adeea73d5d5c22a0ce1952f8aba6d66007615cd1698d4ac85ef1fcf15
|
||
0031d1435d9
|
||
envelope: ac13171b2f17bc2c74997f0fce1e1f35bec6b91fe2e12dbd323d23ba7a3
|
||
8dfec1ac902dc5589e9a5f0de56ad685ea8486210ef41449cd4d8712828913c5d2b68
|
||
0b2b3af4a26c765cff329bfb66d38ecf1d6cfa9e7a73c222c6efe0d9520f7d7c
|
||
handshake_secret: 5e723bed1e5276de2503419eba9da61ead573109c4012268323
|
||
98c7e08155b885bfe7bc93451f9d887a0c1d0c19233e40a8e47b347a9ac3907f94032
|
||
a4cff64f
|
||
server_mac_key: dad66bb9251073d17a13f8e5500f36e5998e3cde520ca0738e708
|
||
5af62fd97812eb79a745c94d0bf8a6ac17f980cf435504cf64041eeb6bb237796d2c7
|
||
f81e9a
|
||
client_mac_key: f816fe2914f7c5b29852385615d7c7f31ac122adf202d7ccd4976
|
||
06d7aabd48930323d1d02b1cc9ecd456c4de6f46c7950becb18bffd921dd5876381b5
|
||
486ffe
|
||
oprf_key: 5d4c6a8b7c7138182afb4345d1fae6a9f18a1744afbcc3854f8f5a2b4b4
|
||
c6d05
|
||
</pre><a href="#appendix-C.1.2.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-1">
|
||
<section id="appendix-C.1.2.4">
|
||
<h5 id="name-output-values-2">
|
||
<a href="#appendix-C.1.2.4" class="section-number selfRef">C.1.2.4. </a><a href="#name-output-values-2" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.2.4-1">
|
||
<pre>
|
||
registration_request: 5059ff249eb1551b7ce4991f3336205bde44a105a032e74
|
||
7d21bf382e75f7a71
|
||
registration_response: 7408a268083e03abc7097fc05b587834539065e86fb0c7
|
||
b6342fcf5e01e5b019b2fe7af9f48cc502d016729d2fe25cdd433f2c4bc904660b2a3
|
||
82c9b79df1a78
|
||
registration_upload: 76a845464c68a5d2f7e442436bb1424953b17d3e2e289ccb
|
||
accafb57ac5c36751ac5844383c7708077dea41cbefe2fa15724f449e535dd7dd562e
|
||
66f5ecfb95864eadddec9db5874959905117dad40a4524111849799281fefe3c51fa8
|
||
2785c5ac13171b2f17bc2c74997f0fce1e1f35bec6b91fe2e12dbd323d23ba7a38dfe
|
||
c1ac902dc5589e9a5f0de56ad685ea8486210ef41449cd4d8712828913c5d2b680b2b
|
||
3af4a26c765cff329bfb66d38ecf1d6cfa9e7a73c222c6efe0d9520f7d7c
|
||
KE1: c4dedb0ba6ed5d965d6f250fbe554cd45cba5dfcce3ce836e4aee778aa3cd44d
|
||
da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb380cae6a6cc6e29b
|
||
ee50701498605b2c085d7b241ca15ba5c32027dd21ba420b94ce60da326
|
||
KE2: 7e308140890bcde30cbcea28b01ea1ecfbd077cff62c4def8efa075aabcbb471
|
||
38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6dd6ec6
|
||
0bcdb26dc455ddf3e718f1020490c192d70dfc7e403981179d8073d1146a4f9aa1ced
|
||
4e4cd984c657eb3b54ced3848326f70331953d91b02535af44d9fea502150b67fe367
|
||
95dd8914f164e49f81c7688a38928372134b7dccd50e09f8fed9518b7b2f94835b3c4
|
||
fe4c8475e7513f20eb97ff0568a39caee3fd6251876f71cd9960ecef2fe0d0f749498
|
||
6fa3d8b2bb01963537e60efb13981e138e3d4a1c4f62198a9d6fa9170c42c3c71f197
|
||
1b29eb1d5d0bd733e40816c91f7912cc4a292371e7809a9031743e943fb3b56f51de9
|
||
03552fc91fba4e7419029951c3970b2e2f0a9dea218d22e9e4e0000855bb6421aa361
|
||
0d6fc0f4033a6517030d4341
|
||
KE3: 7a026de1d6126905736c3f6d92463a08d209833eb793e46d0f7f15b3e0f62c76
|
||
43763c02bbc6b8d3d15b63250cae98171e9260f1ffa789750f534ac11a0176d5
|
||
export_key: 1ef15b4fa99e8a852412450ab78713aad30d21fa6966c9b8c9fb3262a
|
||
970dc62950d4dd4ed62598229b1b72794fc0335199d9f7fcc6eaedde92cc04870e63f
|
||
16
|
||
session_key: ae7951123ab5befc27e62e63f52cf472d6236cb386c968cc47b7e34f
|
||
866aa4bc7638356a73cfce92becf39d6a7d32a1861f12130e824241fe6cab34fbd471
|
||
a57
|
||
</pre><a href="#appendix-C.1.2.4-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="opaque-3dh-real-test-vector-3">
|
||
<section id="appendix-C.1.3">
|
||
<h4 id="name-opaque-3dh-real-test-vector-3">
|
||
<a href="#appendix-C.1.3" class="section-number selfRef">C.1.3. </a><a href="#name-opaque-3dh-real-test-vector-3" class="section-name selfRef">OPAQUE-3DH Real Test Vector 3</a>
|
||
</h4>
|
||
<div id="configuration-2">
|
||
<section id="appendix-C.1.3.1">
|
||
<h5 id="name-configuration-3">
|
||
<a href="#appendix-C.1.3.1" class="section-number selfRef">C.1.3.1. </a><a href="#name-configuration-3" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.3.1-1">
|
||
<pre>
|
||
OPRF: ristretto255-SHA512
|
||
Hash: SHA512
|
||
KSF: Identity
|
||
KDF: HKDF-SHA512
|
||
MAC: HMAC-SHA512
|
||
Group: curve25519
|
||
Context: 4f50415155452d504f43
|
||
Nh: 64
|
||
Npk: 32
|
||
Nsk: 32
|
||
Nm: 64
|
||
Nx: 64
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.1.3.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-2">
|
||
<section id="appendix-C.1.3.2">
|
||
<h5 id="name-input-values-3">
|
||
<a href="#appendix-C.1.3.2" class="section-number selfRef">C.1.3.2. </a><a href="#name-input-values-3" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.3.2-1">
|
||
<pre>
|
||
oprf_seed: a78342ab84d3d30f08d5a9630c79bf311c31ed7f85d9d4959bf492ec67
|
||
a0eec8a67dfbf4497248eebd49e878aab173e5e4ff76354288fdd53e949a5f7c9f7f1
|
||
b
|
||
credential_identifier: 31323334
|
||
password: 436f7272656374486f72736542617474657279537461706c65
|
||
envelope_nonce: 40d6b67fdd7da7c49894750754514dbd2070a407166bd2a5237cc
|
||
a9bf44d6e0b
|
||
masking_nonce: 38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80
|
||
f612fdfc6d
|
||
server_private_key: c06139381df63bfc91c850db0b9cfbec7a62e86d80040a41a
|
||
a7725bf0e79d564
|
||
server_public_key: a41e28269b4e97a66468cc00c5a57753e192e1527669897706
|
||
88aa90486ef031
|
||
server_nonce: 71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e
|
||
138e3d4a1
|
||
client_nonce: da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb38
|
||
0cae6a6cc
|
||
client_keyshare_seed: 82850a697b42a505f5b68fcdafce8c31f0af2b581f063cf
|
||
1091933541936304b
|
||
server_keyshare_seed: 05a4f54206eef1ba2f615bc0aa285cb22f26d1153b5b40a
|
||
1e85ff80da12f982f
|
||
blind_registration: c575731ffe1cb0ca5ba63b42c4699767b8b9ab78ba39316ee
|
||
04baddb2034a70a
|
||
blind_login: 6ecc102d2e7a7cf49617aad7bbe188556792d4acd60a1a8a8d2b65d4
|
||
b0790308
|
||
</pre><a href="#appendix-C.1.3.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="intermediate-values-2">
|
||
<section id="appendix-C.1.3.3">
|
||
<h5 id="name-intermediate-values-3">
|
||
<a href="#appendix-C.1.3.3" class="section-number selfRef">C.1.3.3. </a><a href="#name-intermediate-values-3" class="section-name selfRef">Intermediate Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.3.3-1">
|
||
<pre>
|
||
client_public_key: 0936ea94ab030ec332e29050d266c520e916731a052d05ced7
|
||
e0cfe751142b48
|
||
auth_key: 7e880ab484f750e80e6f839d975aff476070ce65066d85ea62523d1d576
|
||
4739d91307fac47186a4ab935e6a5c7f70cb47faa9473311947502c022cc67ae9440c
|
||
randomized_password: 3a602c295a9c323d9362fe286f104567ed6862b25dbe30fa
|
||
da844f19e41cf40047424b7118e15dc2c1a815a70fea5c8de6c30aa61440cd4b4b5e8
|
||
f3963fbb2e1
|
||
envelope: 40d6b67fdd7da7c49894750754514dbd2070a407166bd2a5237cca9bf44
|
||
d6e0b20c1e81fef28e92e897ca8287d49a55075b47c3988ff0fff367d79a3e350ccac
|
||
150b4a3ff48b4770c8e84e437b3d4e68d2b95833f7788f7eb93fa6a8afb85ecb
|
||
handshake_secret: 178c8c15e025252380c3edb1c6ad8ac52573b38d536099e2f86
|
||
5786f5e31c642608550c0c6f281c37ce259667dd72768af31630e0eb36f1096a2e642
|
||
1c2aa163
|
||
server_mac_key: f3c6a8e069c54bb0d8905139f723c9e22f5c662dc08848243a665
|
||
4c8223800019b9823523d84da2ef67ca1c14277630aace464c113be8a0a658c39e181
|
||
a8bb71
|
||
client_mac_key: b1ee7ce52dbd0ab72872924ff11596cb196bbabfc319e74aca78a
|
||
de54a0f74dd15dcf5621f6d2e79161b0c9b701381d494836dedbb86e584a65b34267a
|
||
370e01
|
||
oprf_key: 62ef7f7d9506a14600c34f642aaf6ef8019cc82a6755db4fded5248ea14
|
||
6030a
|
||
</pre><a href="#appendix-C.1.3.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-2">
|
||
<section id="appendix-C.1.3.4">
|
||
<h5 id="name-output-values-3">
|
||
<a href="#appendix-C.1.3.4" class="section-number selfRef">C.1.3.4. </a><a href="#name-output-values-3" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.3.4-1">
|
||
<pre>
|
||
registration_request: 26f3dbfd76b8e5f85b4da604f42889a7d4b1bc919f65538
|
||
1a67de02c59fd5436
|
||
registration_response: 506e8f1b89c098fb89b5b6210a05f7898cafdaea221761
|
||
e8d5272fc39e0f9f08a41e28269b4e97a66468cc00c5a57753e192e15276698977068
|
||
8aa90486ef031
|
||
registration_upload: 0936ea94ab030ec332e29050d266c520e916731a052d05ce
|
||
d7e0cfe751142b486d23c6ed818882f9bdfdcf91389fcbc0b7a3faf92bd0bd6be4a1e
|
||
7730277b694fc7c6ba327fbe786af18487688e0f7c148bbd54dc2fc80c28e7a976d9e
|
||
f53c3540d6b67fdd7da7c49894750754514dbd2070a407166bd2a5237cca9bf44d6e0
|
||
b20c1e81fef28e92e897ca8287d49a55075b47c3988ff0fff367d79a3e350ccac150b
|
||
4a3ff48b4770c8e84e437b3d4e68d2b95833f7788f7eb93fa6a8afb85ecb
|
||
KE1: c4dedb0ba6ed5d965d6f250fbe554cd45cba5dfcce3ce836e4aee778aa3cd44d
|
||
da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb380cae6a6cc10a83
|
||
b9117d3798cb2957fbdb0268a0d63dbf9d66bde5c00c78affd80026c911
|
||
KE2: 9a0e5a1514f62e005ea098b0d8cf6750e358c4389e6add1c52aed9500fa19d00
|
||
38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6d22cc3
|
||
1127d6f0096755be3c3d2dd6287795c317aeea10c9485bf4f419a786642c19a8f151c
|
||
eb5e8767d175248c62c017de94057398d28bf0ed00d1b50ee4f812fd9afddf98af8cd
|
||
58067ca43b0633b6cadd0e9d987f89623fed4d3583bdf6910c425600e90dab3c6b351
|
||
3188a465461a67f6bbc47aeba808f7f7e2c6d66f5c3271cd9960ecef2fe0d0f749498
|
||
6fa3d8b2bb01963537e60efb13981e138e3d4a141f55f0bef355cfb34ccd468fdacad
|
||
75865ee7efef95f4cb6c25d477f720502676f06a3b806da262139bf3fa76a1090b94d
|
||
ac78bc3bc6f8747d5b35acf94eff3ec2ebe7d49b8cf16be64120b279fe92664e47be5
|
||
da7e60f08f12e91192652f79
|
||
KE3: 550e923829a544496d8316c490da2b979b78c730dd75be3a17f237a26432c19f
|
||
bba54b6a0467b1c22ecbd6794bc5fa5b04215ba1ef974c6b090baa42c5bb984f
|
||
export_key: 9dec51d6d0f6ce7e4345f10961053713b07310cc2e45872f57bbd2fe5
|
||
070fdf0fb5b77c7ddaa2f3dc5c35132df7417ad7fefe0f690ad266e5a54a21d045c9c
|
||
38
|
||
session_key: fd2fdd07c1bcc88e81c1b1d1de5ad62dfdef1c0b8209ff9d671e1fac
|
||
55ce9c34d381c1fb2703ff53a797f77daccbe33047ccc167b8105171e10ec962eea20
|
||
3aa
|
||
</pre><a href="#appendix-C.1.3.4-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="opaque-3dh-real-test-vector-4">
|
||
<section id="appendix-C.1.4">
|
||
<h4 id="name-opaque-3dh-real-test-vector-4">
|
||
<a href="#appendix-C.1.4" class="section-number selfRef">C.1.4. </a><a href="#name-opaque-3dh-real-test-vector-4" class="section-name selfRef">OPAQUE-3DH Real Test Vector 4</a>
|
||
</h4>
|
||
<div id="configuration-3">
|
||
<section id="appendix-C.1.4.1">
|
||
<h5 id="name-configuration-4">
|
||
<a href="#appendix-C.1.4.1" class="section-number selfRef">C.1.4.1. </a><a href="#name-configuration-4" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.4.1-1">
|
||
<pre>
|
||
OPRF: ristretto255-SHA512
|
||
Hash: SHA512
|
||
KSF: Identity
|
||
KDF: HKDF-SHA512
|
||
MAC: HMAC-SHA512
|
||
Group: curve25519
|
||
Context: 4f50415155452d504f43
|
||
Nh: 64
|
||
Npk: 32
|
||
Nsk: 32
|
||
Nm: 64
|
||
Nx: 64
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.1.4.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-3">
|
||
<section id="appendix-C.1.4.2">
|
||
<h5 id="name-input-values-4">
|
||
<a href="#appendix-C.1.4.2" class="section-number selfRef">C.1.4.2. </a><a href="#name-input-values-4" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.4.2-1">
|
||
<pre>
|
||
client_identity: 616c696365
|
||
server_identity: 626f62
|
||
oprf_seed: a78342ab84d3d30f08d5a9630c79bf311c31ed7f85d9d4959bf492ec67
|
||
a0eec8a67dfbf4497248eebd49e878aab173e5e4ff76354288fdd53e949a5f7c9f7f1
|
||
b
|
||
credential_identifier: 31323334
|
||
password: 436f7272656374486f72736542617474657279537461706c65
|
||
envelope_nonce: 40d6b67fdd7da7c49894750754514dbd2070a407166bd2a5237cc
|
||
a9bf44d6e0b
|
||
masking_nonce: 38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80
|
||
f612fdfc6d
|
||
server_private_key: c06139381df63bfc91c850db0b9cfbec7a62e86d80040a41a
|
||
a7725bf0e79d564
|
||
server_public_key: a41e28269b4e97a66468cc00c5a57753e192e1527669897706
|
||
88aa90486ef031
|
||
server_nonce: 71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e
|
||
138e3d4a1
|
||
client_nonce: da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb38
|
||
0cae6a6cc
|
||
client_keyshare_seed: 82850a697b42a505f5b68fcdafce8c31f0af2b581f063cf
|
||
1091933541936304b
|
||
server_keyshare_seed: 05a4f54206eef1ba2f615bc0aa285cb22f26d1153b5b40a
|
||
1e85ff80da12f982f
|
||
blind_registration: c575731ffe1cb0ca5ba63b42c4699767b8b9ab78ba39316ee
|
||
04baddb2034a70a
|
||
blind_login: 6ecc102d2e7a7cf49617aad7bbe188556792d4acd60a1a8a8d2b65d4
|
||
b0790308
|
||
</pre><a href="#appendix-C.1.4.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="intermediate-values-3">
|
||
<section id="appendix-C.1.4.3">
|
||
<h5 id="name-intermediate-values-4">
|
||
<a href="#appendix-C.1.4.3" class="section-number selfRef">C.1.4.3. </a><a href="#name-intermediate-values-4" class="section-name selfRef">Intermediate Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.4.3-1">
|
||
<pre>
|
||
client_public_key: 0936ea94ab030ec332e29050d266c520e916731a052d05ced7
|
||
e0cfe751142b48
|
||
auth_key: 7e880ab484f750e80e6f839d975aff476070ce65066d85ea62523d1d576
|
||
4739d91307fac47186a4ab935e6a5c7f70cb47faa9473311947502c022cc67ae9440c
|
||
randomized_password: 3a602c295a9c323d9362fe286f104567ed6862b25dbe30fa
|
||
da844f19e41cf40047424b7118e15dc2c1a815a70fea5c8de6c30aa61440cd4b4b5e8
|
||
f3963fbb2e1
|
||
envelope: 40d6b67fdd7da7c49894750754514dbd2070a407166bd2a5237cca9bf44
|
||
d6e0bb4c0eab6143959a650c5f6b32acf162b1fbe95bb36c5c4f99df53865c4d3537d
|
||
69061d80522d772cd0efdbe91f817f6bf7259a56e20b4eb9cbe9443702f4b759
|
||
handshake_secret: 13e7dc6afa5334b9dfffe26bee3caf744ef4add176caee464cd
|
||
eb3d37303b90de35a8bf095df84471ac77d705f12fe232f1571de1d6a001d3e808998
|
||
73a142dc
|
||
server_mac_key: a58135acfb2bde92d506cf59119729a6404ad94eba294e4b52a63
|
||
baf58cfe03f21bcf735222c7f2c27a60bd958be7f6aed50dc03a78f64e7ae4ac1ff07
|
||
1b95aa
|
||
client_mac_key: 1e1a8ba156aadc4a302f707d2193c9dab477b355f430d450dd407
|
||
ce40dc75613f76ec33dec494f8a6bfdcf951eb060dac33e6572c693954fe92e33730c
|
||
9ab0a2
|
||
oprf_key: 62ef7f7d9506a14600c34f642aaf6ef8019cc82a6755db4fded5248ea14
|
||
6030a
|
||
</pre><a href="#appendix-C.1.4.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-3">
|
||
<section id="appendix-C.1.4.4">
|
||
<h5 id="name-output-values-4">
|
||
<a href="#appendix-C.1.4.4" class="section-number selfRef">C.1.4.4. </a><a href="#name-output-values-4" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.4.4-1">
|
||
<pre>
|
||
registration_request: 26f3dbfd76b8e5f85b4da604f42889a7d4b1bc919f65538
|
||
1a67de02c59fd5436
|
||
registration_response: 506e8f1b89c098fb89b5b6210a05f7898cafdaea221761
|
||
e8d5272fc39e0f9f08a41e28269b4e97a66468cc00c5a57753e192e15276698977068
|
||
8aa90486ef031
|
||
registration_upload: 0936ea94ab030ec332e29050d266c520e916731a052d05ce
|
||
d7e0cfe751142b486d23c6ed818882f9bdfdcf91389fcbc0b7a3faf92bd0bd6be4a1e
|
||
7730277b694fc7c6ba327fbe786af18487688e0f7c148bbd54dc2fc80c28e7a976d9e
|
||
f53c3540d6b67fdd7da7c49894750754514dbd2070a407166bd2a5237cca9bf44d6e0
|
||
bb4c0eab6143959a650c5f6b32acf162b1fbe95bb36c5c4f99df53865c4d3537d6906
|
||
1d80522d772cd0efdbe91f817f6bf7259a56e20b4eb9cbe9443702f4b759
|
||
KE1: c4dedb0ba6ed5d965d6f250fbe554cd45cba5dfcce3ce836e4aee778aa3cd44d
|
||
da7e07376d6d6f034cfa9bb537d11b8c6b4238c334333d1f0aebb380cae6a6cc10a83
|
||
b9117d3798cb2957fbdb0268a0d63dbf9d66bde5c00c78affd80026c911
|
||
KE2: 9a0e5a1514f62e005ea098b0d8cf6750e358c4389e6add1c52aed9500fa19d00
|
||
38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6d22cc3
|
||
1127d6f0096755be3c3d2dd6287795c317aeea10c9485bf4f419a786642c19a8f151c
|
||
eb5e8767d175248c62c017de94057398d28bf0ed00d1b50ee4f812699bff7663be3c5
|
||
d59de94d8e7e58817c7da005b39c25d25555c929e1c5cf6c1b82837b1367c839aab56
|
||
a422c0d97719426a79a16f9869cf852100597b23b5a071cd9960ecef2fe0d0f749498
|
||
6fa3d8b2bb01963537e60efb13981e138e3d4a141f55f0bef355cfb34ccd468fdacad
|
||
75865ee7efef95f4cb6c25d477f72050267cc22c87edbf3ecaca64cb33bc60dc3bfc5
|
||
51e365f0d46a7fed0e09d96f9afbb48868f5bb3c3e05a86ed8c9476fc22c58306c5a2
|
||
91be34388e09548ba9d70f39
|
||
KE3: d16344e791c3f18594d22ba068984fa18ec1e9bead662b75f66826ffd627932f
|
||
cd1ec40cd01dcf5f63f4055ebe45c7717a57a833aad360256cf1e1c20c0eae1c
|
||
export_key: 9dec51d6d0f6ce7e4345f10961053713b07310cc2e45872f57bbd2fe5
|
||
070fdf0fb5b77c7ddaa2f3dc5c35132df7417ad7fefe0f690ad266e5a54a21d045c9c
|
||
38
|
||
session_key: f6116d3aa0e4089a179713bad4d98ed5cb57e5443cae8d36ef78996f
|
||
a60f3dc6e9fcdd63c001596b06dbc1285d80211035cc0e485506b3f7a650cbf78c5bf
|
||
fc9
|
||
</pre><a href="#appendix-C.1.4.4-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="opaque-3dh-real-test-vector-5">
|
||
<section id="appendix-C.1.5">
|
||
<h4 id="name-opaque-3dh-real-test-vector-5">
|
||
<a href="#appendix-C.1.5" class="section-number selfRef">C.1.5. </a><a href="#name-opaque-3dh-real-test-vector-5" class="section-name selfRef">OPAQUE-3DH Real Test Vector 5</a>
|
||
</h4>
|
||
<div id="configuration-4">
|
||
<section id="appendix-C.1.5.1">
|
||
<h5 id="name-configuration-5">
|
||
<a href="#appendix-C.1.5.1" class="section-number selfRef">C.1.5.1. </a><a href="#name-configuration-5" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.5.1-1">
|
||
<pre>
|
||
OPRF: P256-SHA256
|
||
Hash: SHA256
|
||
KSF: Identity
|
||
KDF: HKDF-SHA256
|
||
MAC: HMAC-SHA256
|
||
Group: P256_XMD:SHA-256_SSWU_RO_
|
||
Context: 4f50415155452d504f43
|
||
Nh: 32
|
||
Npk: 33
|
||
Nsk: 32
|
||
Nm: 32
|
||
Nx: 32
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.1.5.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-4">
|
||
<section id="appendix-C.1.5.2">
|
||
<h5 id="name-input-values-5">
|
||
<a href="#appendix-C.1.5.2" class="section-number selfRef">C.1.5.2. </a><a href="#name-input-values-5" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.5.2-1">
|
||
<pre>
|
||
oprf_seed: 62f60b286d20ce4fd1d64809b0021dad6ed5d52a2c8cf27ae6582543a0
|
||
a8dce2
|
||
credential_identifier: 31323334
|
||
password: 436f7272656374486f72736542617474657279537461706c65
|
||
envelope_nonce: a921f2a014513bd8a90e477a629794e89fec12d12206dde662ebd
|
||
cf65670e51f
|
||
masking_nonce: 38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80
|
||
f612fdfc6d
|
||
server_private_key: c36139381df63bfc91c850db0b9cfbec7a62e86d80040a41a
|
||
a7725bf0e79d5e5
|
||
server_public_key: 035f40ff9cf88aa1f5cd4fe5fd3da9ea65a4923a5594f84fd9
|
||
f2092d6067784874
|
||
server_nonce: 71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e
|
||
138e3d4a1
|
||
client_nonce: ab3d33bde0e93eda72392346a7a73051110674bbf6b1b7ffab8be4f
|
||
91fdaeeb1
|
||
client_keyshare_seed: 633b875d74d1556d2a2789309972b06db21dfcc4f5ad51d
|
||
7e74d783b7cfab8dc
|
||
server_keyshare_seed: 05a4f54206eef1ba2f615bc0aa285cb22f26d1153b5b40a
|
||
1e85ff80da12f982f
|
||
blind_registration: 411bf1a62d119afe30df682b91a0a33d777972d4f2daa4b34
|
||
ca527d597078153
|
||
blind_login: c497fddf6056d241e6cf9fb7ac37c384f49b357a221eb0a802c989b9
|
||
942256c1
|
||
</pre><a href="#appendix-C.1.5.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="intermediate-values-4">
|
||
<section id="appendix-C.1.5.3">
|
||
<h5 id="name-intermediate-values-5">
|
||
<a href="#appendix-C.1.5.3" class="section-number selfRef">C.1.5.3. </a><a href="#name-intermediate-values-5" class="section-name selfRef">Intermediate Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.5.3-1">
|
||
<pre>
|
||
client_public_key: 03b218507d978c3db570ca994aaf36695a731ddb2db272c817
|
||
f79746fc37ae5214
|
||
auth_key: 5bd4be1602516092dc5078f8d699f5721dc1720a49fb80d8e5c16377abd
|
||
0987b
|
||
randomized_password: 06be0a1a51d56557a3adad57ba29c5510565dcd8b5078fa3
|
||
19151b9382258fb0
|
||
envelope: a921f2a014513bd8a90e477a629794e89fec12d12206dde662ebdcf6567
|
||
0e51fad30bbcfc1f8eda0211553ab9aaf26345ad59a128e80188f035fe4924fad67b8
|
||
handshake_secret: 83a932431a8f25bad042f008efa2b07c6cd0faa8285f335b636
|
||
3546a9f9b235f
|
||
server_mac_key: 13e928581febfad28855e3e7f03306d61bd69489686f621535d44
|
||
a1365b73b0d
|
||
client_mac_key: afdc53910c25183b08b930e6953c35b3466276736d9de2e9c5efa
|
||
f150f4082c5
|
||
oprf_key: 2dfb5cb9aa1476093be74ca0d43e5b02862a05f5d6972614d7433acdc66
|
||
f7f31
|
||
</pre><a href="#appendix-C.1.5.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-4">
|
||
<section id="appendix-C.1.5.4">
|
||
<h5 id="name-output-values-5">
|
||
<a href="#appendix-C.1.5.4" class="section-number selfRef">C.1.5.4. </a><a href="#name-output-values-5" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.5.4-1">
|
||
<pre>
|
||
registration_request: 029e949a29cfa0bf7c1287333d2fb3dc586c41aa652f507
|
||
0d26a5315a1b50229f8
|
||
registration_response: 0350d3694c00978f00a5ce7cd08a00547e4ab5fb5fc2b2
|
||
f6717cdaa6c89136efef035f40ff9cf88aa1f5cd4fe5fd3da9ea65a4923a5594f84fd
|
||
9f2092d6067784874
|
||
registration_upload: 03b218507d978c3db570ca994aaf36695a731ddb2db272c8
|
||
17f79746fc37ae52147f0ed53532d3ae8e505ecc70d42d2b814b6b0e48156def71ea0
|
||
29148b2803aafa921f2a014513bd8a90e477a629794e89fec12d12206dde662ebdcf6
|
||
5670e51fad30bbcfc1f8eda0211553ab9aaf26345ad59a128e80188f035fe4924fad6
|
||
7b8
|
||
KE1: 037342f0bcb3ecea754c1e67576c86aa90c1de3875f390ad599a26686cdfee6e
|
||
07ab3d33bde0e93eda72392346a7a73051110674bbf6b1b7ffab8be4f91fdaeeb1022
|
||
ed3f32f318f81bab80da321fecab3cd9b6eea11a95666dfa6beeaab321280b6
|
||
KE2: 0246da9fe4d41d5ba69faa6c509a1d5bafd49a48615a47a8dd4b0823cc147648
|
||
1138fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6d2f0
|
||
c547f70deaeca54d878c14c1aa5e1ab405dec833777132eea905c2fbb12504a67dcbe
|
||
0e66740c76b62c13b04a38a77926e19072953319ec65e41f9bfd2ae26837b6ce688bf
|
||
9af2542f04eec9ab96a1b9328812dc2f5c89182ed47fead61f09f71cd9960ecef2fe0
|
||
d0f7494986fa3d8b2bb01963537e60efb13981e138e3d4a103c1701353219b53acf33
|
||
7bf6456a83cefed8f563f1040b65afbf3b65d3bc9a19b50a73b145bc87a157e8c58c0
|
||
342e2047ee22ae37b63db17e0a82a30fcc4ecf7b
|
||
KE3: e97cab4433aa39d598e76f13e768bba61c682947bdcf9936035e8a3a3ebfb66e
|
||
export_key: c3c9a1b0e33ac84dd83d0b7e8af6794e17e7a3caadff289fbd9dc769a
|
||
853c64b
|
||
session_key: 484ad345715ccce138ca49e4ea362c6183f0949aaaa1125dc3bc3f80
|
||
876e7cd1
|
||
</pre><a href="#appendix-C.1.5.4-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="opaque-3dh-real-test-vector-6">
|
||
<section id="appendix-C.1.6">
|
||
<h4 id="name-opaque-3dh-real-test-vector-6">
|
||
<a href="#appendix-C.1.6" class="section-number selfRef">C.1.6. </a><a href="#name-opaque-3dh-real-test-vector-6" class="section-name selfRef">OPAQUE-3DH Real Test Vector 6</a>
|
||
</h4>
|
||
<div id="configuration-5">
|
||
<section id="appendix-C.1.6.1">
|
||
<h5 id="name-configuration-6">
|
||
<a href="#appendix-C.1.6.1" class="section-number selfRef">C.1.6.1. </a><a href="#name-configuration-6" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.6.1-1">
|
||
<pre>
|
||
OPRF: P256-SHA256
|
||
Hash: SHA256
|
||
KSF: Identity
|
||
KDF: HKDF-SHA256
|
||
MAC: HMAC-SHA256
|
||
Group: P256_XMD:SHA-256_SSWU_RO_
|
||
Context: 4f50415155452d504f43
|
||
Nh: 32
|
||
Npk: 33
|
||
Nsk: 32
|
||
Nm: 32
|
||
Nx: 32
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.1.6.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-5">
|
||
<section id="appendix-C.1.6.2">
|
||
<h5 id="name-input-values-6">
|
||
<a href="#appendix-C.1.6.2" class="section-number selfRef">C.1.6.2. </a><a href="#name-input-values-6" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.6.2-1">
|
||
<pre>
|
||
client_identity: 616c696365
|
||
server_identity: 626f62
|
||
oprf_seed: 62f60b286d20ce4fd1d64809b0021dad6ed5d52a2c8cf27ae6582543a0
|
||
a8dce2
|
||
credential_identifier: 31323334
|
||
password: 436f7272656374486f72736542617474657279537461706c65
|
||
envelope_nonce: a921f2a014513bd8a90e477a629794e89fec12d12206dde662ebd
|
||
cf65670e51f
|
||
masking_nonce: 38fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80
|
||
f612fdfc6d
|
||
server_private_key: c36139381df63bfc91c850db0b9cfbec7a62e86d80040a41a
|
||
a7725bf0e79d5e5
|
||
server_public_key: 035f40ff9cf88aa1f5cd4fe5fd3da9ea65a4923a5594f84fd9
|
||
f2092d6067784874
|
||
server_nonce: 71cd9960ecef2fe0d0f7494986fa3d8b2bb01963537e60efb13981e
|
||
138e3d4a1
|
||
client_nonce: ab3d33bde0e93eda72392346a7a73051110674bbf6b1b7ffab8be4f
|
||
91fdaeeb1
|
||
client_keyshare_seed: 633b875d74d1556d2a2789309972b06db21dfcc4f5ad51d
|
||
7e74d783b7cfab8dc
|
||
server_keyshare_seed: 05a4f54206eef1ba2f615bc0aa285cb22f26d1153b5b40a
|
||
1e85ff80da12f982f
|
||
blind_registration: 411bf1a62d119afe30df682b91a0a33d777972d4f2daa4b34
|
||
ca527d597078153
|
||
blind_login: c497fddf6056d241e6cf9fb7ac37c384f49b357a221eb0a802c989b9
|
||
942256c1
|
||
</pre><a href="#appendix-C.1.6.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="intermediate-values-5">
|
||
<section id="appendix-C.1.6.3">
|
||
<h5 id="name-intermediate-values-6">
|
||
<a href="#appendix-C.1.6.3" class="section-number selfRef">C.1.6.3. </a><a href="#name-intermediate-values-6" class="section-name selfRef">Intermediate Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.6.3-1">
|
||
<pre>
|
||
client_public_key: 03b218507d978c3db570ca994aaf36695a731ddb2db272c817
|
||
f79746fc37ae5214
|
||
auth_key: 5bd4be1602516092dc5078f8d699f5721dc1720a49fb80d8e5c16377abd
|
||
0987b
|
||
randomized_password: 06be0a1a51d56557a3adad57ba29c5510565dcd8b5078fa3
|
||
19151b9382258fb0
|
||
envelope: a921f2a014513bd8a90e477a629794e89fec12d12206dde662ebdcf6567
|
||
0e51f4d7773a36a208a866301dbb2858e40dc5638017527cf91aef32d3848eebe0971
|
||
handshake_secret: 80bdcc498f22de492e90ee8101fcc7c101e158dd49c77f7c283
|
||
816ae329ed62f
|
||
server_mac_key: 0f82432fbdb5b90daf27a91a3acc42299a9590dba1b77932c2207
|
||
b4cb3d4a157
|
||
client_mac_key: 7f629eb0b1b69979b07ca1f564b3e92ed22f07569fd1d11725d93
|
||
e46731fbe71
|
||
oprf_key: 2dfb5cb9aa1476093be74ca0d43e5b02862a05f5d6972614d7433acdc66
|
||
f7f31
|
||
</pre><a href="#appendix-C.1.6.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-5">
|
||
<section id="appendix-C.1.6.4">
|
||
<h5 id="name-output-values-6">
|
||
<a href="#appendix-C.1.6.4" class="section-number selfRef">C.1.6.4. </a><a href="#name-output-values-6" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.1.6.4-1">
|
||
<pre>
|
||
registration_request: 029e949a29cfa0bf7c1287333d2fb3dc586c41aa652f507
|
||
0d26a5315a1b50229f8
|
||
registration_response: 0350d3694c00978f00a5ce7cd08a00547e4ab5fb5fc2b2
|
||
f6717cdaa6c89136efef035f40ff9cf88aa1f5cd4fe5fd3da9ea65a4923a5594f84fd
|
||
9f2092d6067784874
|
||
registration_upload: 03b218507d978c3db570ca994aaf36695a731ddb2db272c8
|
||
17f79746fc37ae52147f0ed53532d3ae8e505ecc70d42d2b814b6b0e48156def71ea0
|
||
29148b2803aafa921f2a014513bd8a90e477a629794e89fec12d12206dde662ebdcf6
|
||
5670e51f4d7773a36a208a866301dbb2858e40dc5638017527cf91aef32d3848eebe0
|
||
971
|
||
KE1: 037342f0bcb3ecea754c1e67576c86aa90c1de3875f390ad599a26686cdfee6e
|
||
07ab3d33bde0e93eda72392346a7a73051110674bbf6b1b7ffab8be4f91fdaeeb1022
|
||
ed3f32f318f81bab80da321fecab3cd9b6eea11a95666dfa6beeaab321280b6
|
||
KE2: 0246da9fe4d41d5ba69faa6c509a1d5bafd49a48615a47a8dd4b0823cc147648
|
||
1138fe59af0df2c79f57b8780278f5ae47355fe1f817119041951c80f612fdfc6d2f0
|
||
c547f70deaeca54d878c14c1aa5e1ab405dec833777132eea905c2fbb12504a67dcbe
|
||
0e66740c76b62c13b04a38a77926e19072953319ec65e41f9bfd2ae268d7f10604202
|
||
1c80300e4c6f585980cf39fc51a4a6bba41b0729f9b240c729e5671cd9960ecef2fe0
|
||
d0f7494986fa3d8b2bb01963537e60efb13981e138e3d4a103c1701353219b53acf33
|
||
7bf6456a83cefed8f563f1040b65afbf3b65d3bc9a19b84922c7e5d074838a8f27859
|
||
2c53f61fb59f031e85ad480c0c71086b871e1b24
|
||
KE3: 46833578cee137775f6be3f01b80748daac5a694101ad0e9e7025480552da56a
|
||
export_key: c3c9a1b0e33ac84dd83d0b7e8af6794e17e7a3caadff289fbd9dc769a
|
||
853c64b
|
||
session_key: 27766fabd8dd88ff37fbd0ef1a491e601d10d9f016c2b28c4bd1b0fb
|
||
7511a3c3
|
||
</pre><a href="#appendix-C.1.6.4-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="fake-vectors">
|
||
<section id="appendix-C.2">
|
||
<h3 id="name-fake-test-vectors">
|
||
<a href="#appendix-C.2" class="section-number selfRef">C.2. </a><a href="#name-fake-test-vectors" class="section-name selfRef">Fake Test Vectors</a>
|
||
</h3>
|
||
<div id="opaque-3dh-fake-test-vector-1">
|
||
<section id="appendix-C.2.1">
|
||
<h4 id="name-opaque-3dh-fake-test-vector">
|
||
<a href="#appendix-C.2.1" class="section-number selfRef">C.2.1. </a><a href="#name-opaque-3dh-fake-test-vector" class="section-name selfRef">OPAQUE-3DH Fake Test Vector 1</a>
|
||
</h4>
|
||
<div id="configuration-6">
|
||
<section id="appendix-C.2.1.1">
|
||
<h5 id="name-configuration-7">
|
||
<a href="#appendix-C.2.1.1" class="section-number selfRef">C.2.1.1. </a><a href="#name-configuration-7" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.1.1-1">
|
||
<pre>
|
||
OPRF: ristretto255-SHA512
|
||
Hash: SHA512
|
||
KSF: Identity
|
||
KDF: HKDF-SHA512
|
||
MAC: HMAC-SHA512
|
||
Group: ristretto255
|
||
Context: 4f50415155452d504f43
|
||
Nh: 64
|
||
Npk: 32
|
||
Nsk: 32
|
||
Nm: 64
|
||
Nx: 64
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.2.1.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-6">
|
||
<section id="appendix-C.2.1.2">
|
||
<h5 id="name-input-values-7">
|
||
<a href="#appendix-C.2.1.2" class="section-number selfRef">C.2.1.2. </a><a href="#name-input-values-7" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.1.2-1">
|
||
<pre>
|
||
client_identity: 616c696365
|
||
server_identity: 626f62
|
||
oprf_seed: 743fc168d1f826ad43738933e5adb23da6fb95f95a1b069f0daa0522d0
|
||
a78b617f701fc6aa46d3e7981e70de7765dfcd6b1e13e3369a582eb8dc456b10aa53b
|
||
0
|
||
credential_identifier: 31323334
|
||
masking_nonce: 9c035896a043e70f897d87180c543e7a063b83c1bb728fbd189c61
|
||
9e27b6e5a6
|
||
client_private_key: 2b98980aa95ab53a0f39f0291903d2fdf04b00c167f081416
|
||
9922df873002409
|
||
client_public_key: 84f43f9492e19c22d8bdaa4447cc3d4db1cdb5427a9f852c47
|
||
07921212c36251
|
||
server_private_key: c788585ae8b5ba2942b693b849be0c0426384e41977c18d2e
|
||
81fbe30fd7c9f06
|
||
server_public_key: 825f832667480f08b0c9069da5083ac4d0e9ee31b49c4e0310
|
||
031fea04d52966
|
||
server_nonce: 1e10f6eeab2a7a420bf09da9b27a4639645622c46358de9cf7ae813
|
||
055ae2d12
|
||
client_keyshare_seed: a270dc715dc2b4612bc7864312a05c3e9788ee1bad1f276
|
||
d1e15bdeb4c355e94
|
||
server_keyshare_seed: 360b0937f47d45f6123a4d8f0d0c0814b6120d840ebb8bc
|
||
5b4f6b62df07f78c2
|
||
masking_key: 39ebd51f0e39a07a1c2d2431995b0399bca9996c5d10014d6ebab445
|
||
3dc10ce5cef38ed3df6e56bfff40c2d8dd4671c2b4cf63c3d54860f31fe40220d690b
|
||
b71
|
||
KE1: b0a26dcaca2230b8f5e4b1bcab9c84b586140221bb8b2848486874b0be448905
|
||
42d4e61ed3f8d64cdd3b9d153343eca15b9b0d5e388232793c6376bd2d9cfd0ab641d
|
||
7f20a245a09f1d4dbb6e301661af7f352beb0791d055e48d3645232f77f
|
||
</pre><a href="#appendix-C.2.1.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-6">
|
||
<section id="appendix-C.2.1.3">
|
||
<h5 id="name-output-values-7">
|
||
<a href="#appendix-C.2.1.3" class="section-number selfRef">C.2.1.3. </a><a href="#name-output-values-7" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.1.3-1">
|
||
<pre>
|
||
KE2: 928f79ad8df21963e91411b9f55165ba833dea918f441db967cdc09521d22925
|
||
9c035896a043e70f897d87180c543e7a063b83c1bb728fbd189c619e27b6e5a632b5a
|
||
b1bff96636144faa4f9f9afaac75dd88ea99cf5175902ae3f3b2195693f165f11929b
|
||
a510a5978e64dcdabecbd7ee1e4380ce270e58fea58e6462d92964a1aaef72698bca1
|
||
c673baeb04cc2bf7de5f3c2f5553464552d3a0f7698a9ca7f9c5e70c6cb1f706b2f17
|
||
5ab9d04bbd13926e816b6811a50b4aafa9799d5ed7971e10f6eeab2a7a420bf09da9b
|
||
27a4639645622c46358de9cf7ae813055ae2d1298251c5ba55f6b0b2d58d9ff0c88fe
|
||
4176484be62a96db6e2a8c4d431bd1bf27fe6c1d0537603835217d42ebf7b25819827
|
||
32e74892fd28211b31ed33863f0beaf75ba6f59474c0aaf9d78a60a9b2f4cd24d7ab5
|
||
4131b3c8efa192df6b72db4c
|
||
</pre><a href="#appendix-C.2.1.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="opaque-3dh-fake-test-vector-2">
|
||
<section id="appendix-C.2.2">
|
||
<h4 id="name-opaque-3dh-fake-test-vector-">
|
||
<a href="#appendix-C.2.2" class="section-number selfRef">C.2.2. </a><a href="#name-opaque-3dh-fake-test-vector-" class="section-name selfRef">OPAQUE-3DH Fake Test Vector 2</a>
|
||
</h4>
|
||
<div id="configuration-7">
|
||
<section id="appendix-C.2.2.1">
|
||
<h5 id="name-configuration-8">
|
||
<a href="#appendix-C.2.2.1" class="section-number selfRef">C.2.2.1. </a><a href="#name-configuration-8" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.2.1-1">
|
||
<pre>
|
||
OPRF: ristretto255-SHA512
|
||
Hash: SHA512
|
||
KSF: Identity
|
||
KDF: HKDF-SHA512
|
||
MAC: HMAC-SHA512
|
||
Group: curve25519
|
||
Context: 4f50415155452d504f43
|
||
Nh: 64
|
||
Npk: 32
|
||
Nsk: 32
|
||
Nm: 64
|
||
Nx: 64
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.2.2.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-7">
|
||
<section id="appendix-C.2.2.2">
|
||
<h5 id="name-input-values-8">
|
||
<a href="#appendix-C.2.2.2" class="section-number selfRef">C.2.2.2. </a><a href="#name-input-values-8" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.2.2-1">
|
||
<pre>
|
||
client_identity: 616c696365
|
||
server_identity: 626f62
|
||
oprf_seed: 66e650652a8266b2205f31fdd68adeb739a05b5e650b19e7edc75e734a
|
||
1296d6088188ca46c31ae8ccbd42a52ed338c06e53645387a7efbc94b6a0449526155
|
||
e
|
||
credential_identifier: 31323334
|
||
masking_nonce: 9c035896a043e70f897d87180c543e7a063b83c1bb728fbd189c61
|
||
9e27b6e5a6
|
||
client_private_key: 288bf63470199221847bb035d99f96531adf8badd14cb1571
|
||
b48f7a506649660
|
||
client_public_key: 3c64a3153854cc9f0c23aab3c1a19106ec8bab4730736d1d00
|
||
3880a1d5a59005
|
||
server_private_key: 30fbe7e830be1fe8d2187c97414e3826040cbe49b893b6422
|
||
9bab5e85a588846
|
||
server_public_key: 78b3040047ff26572a7619617601a61b9c81899bee92f00cfc
|
||
aa5eed96863555
|
||
server_nonce: 1e10f6eeab2a7a420bf09da9b27a4639645622c46358de9cf7ae813
|
||
055ae2d12
|
||
client_keyshare_seed: a270dc715dc2b4612bc7864312a05c3e9788ee1bad1f276
|
||
d1e15bdeb4c355e94
|
||
server_keyshare_seed: 360b0937f47d45f6123a4d8f0d0c0814b6120d840ebb8bc
|
||
5b4f6b62df07f78c2
|
||
masking_key: 79ad2621b0757a447dff7108a8ae20a068ce67872095620f415ea611
|
||
c9dcc04972fa359538cd2fd6528775ca775487b2b56db642049b8a90526b975a38484
|
||
c6a
|
||
KE1: b0a26dcaca2230b8f5e4b1bcab9c84b586140221bb8b2848486874b0be448905
|
||
42d4e61ed3f8d64cdd3b9d153343eca15b9b0d5e388232793c6376bd2d9cfd0ac059b
|
||
7ba2aec863933ae48816360c7a9022e83d822704f3b0b86c0502a66e574
|
||
</pre><a href="#appendix-C.2.2.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-7">
|
||
<section id="appendix-C.2.2.3">
|
||
<h5 id="name-output-values-8">
|
||
<a href="#appendix-C.2.2.3" class="section-number selfRef">C.2.2.3. </a><a href="#name-output-values-8" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.2.3-1">
|
||
<pre>
|
||
KE2: 6606b6fedbb33f19a81a1feb5149c600fe77252f58acd3080d7504d3dad4922f
|
||
9c035896a043e70f897d87180c543e7a063b83c1bb728fbd189c619e27b6e5a67db39
|
||
8c0f65d8c298eac430abdae4c80e82b552fb940c00f0cbcea853c0f96c1c15099f3d4
|
||
b0e83ecc249613116d605b8d77bb68bdf76994c2bc507e2dcae4176f00afed68ad25c
|
||
f3040a0e991acece31ca532117f5c12816997372ff031ad04ebcdce06c501da24e7b4
|
||
db95343456e2ed260895ec362694230a1fa20e24a9c71e10f6eeab2a7a420bf09da9b
|
||
27a4639645622c46358de9cf7ae813055ae2d122d9055eb8f83e1b497370adad5cc2a
|
||
417bf9be436a792def0c7b7ccb92b9e275d7c663104ea4655bd70570d975c05351655
|
||
d55fbfb392286edb55600a23b55ce18f8c60e0d1960c960412dd08eabc81ba7ca8ae2
|
||
b04aad65462321f51c298010
|
||
</pre><a href="#appendix-C.2.2.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="opaque-3dh-fake-test-vector-3">
|
||
<section id="appendix-C.2.3">
|
||
<h4 id="name-opaque-3dh-fake-test-vector-3">
|
||
<a href="#appendix-C.2.3" class="section-number selfRef">C.2.3. </a><a href="#name-opaque-3dh-fake-test-vector-3" class="section-name selfRef">OPAQUE-3DH Fake Test Vector 3</a>
|
||
</h4>
|
||
<div id="configuration-8">
|
||
<section id="appendix-C.2.3.1">
|
||
<h5 id="name-configuration-9">
|
||
<a href="#appendix-C.2.3.1" class="section-number selfRef">C.2.3.1. </a><a href="#name-configuration-9" class="section-name selfRef">Configuration</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.3.1-1">
|
||
<pre>
|
||
OPRF: P256-SHA256
|
||
Hash: SHA256
|
||
KSF: Identity
|
||
KDF: HKDF-SHA256
|
||
MAC: HMAC-SHA256
|
||
Group: P256_XMD:SHA-256_SSWU_RO_
|
||
Context: 4f50415155452d504f43
|
||
Nh: 32
|
||
Npk: 33
|
||
Nsk: 32
|
||
Nm: 32
|
||
Nx: 32
|
||
Nok: 32
|
||
</pre><a href="#appendix-C.2.3.1-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="input-values-8">
|
||
<section id="appendix-C.2.3.2">
|
||
<h5 id="name-input-values-9">
|
||
<a href="#appendix-C.2.3.2" class="section-number selfRef">C.2.3.2. </a><a href="#name-input-values-9" class="section-name selfRef">Input Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.3.2-1">
|
||
<pre>
|
||
client_identity: 616c696365
|
||
server_identity: 626f62
|
||
oprf_seed: bb1cd59e16ac09bc0cb6d528541695d7eba2239b1613a3db3ade77b362
|
||
80f725
|
||
credential_identifier: 31323334
|
||
masking_nonce: 9c035896a043e70f897d87180c543e7a063b83c1bb728fbd189c61
|
||
9e27b6e5a6
|
||
client_private_key: d423b87899fc61d014fc8330a4e26190fcfa470a3afe59243
|
||
24294af7dbbc1dd
|
||
client_public_key: 03b81708eae026a9370616c22e1e8542fe9dbebd36ce8a2661
|
||
b708e9628f4a57fc
|
||
server_private_key: 34fbe7e830be1fe8d2187c97414e3826040cbe49b893b6422
|
||
9bab5e85a5888c7
|
||
server_public_key: 0221e034c0e202fe883dcfc96802a7624166fed4cfcab4ae30
|
||
cf5f3290d01c88bf
|
||
server_nonce: 1e10f6eeab2a7a420bf09da9b27a4639645622c46358de9cf7ae813
|
||
055ae2d12
|
||
client_keyshare_seed: a270dc715dc2b4612bc7864312a05c3e9788ee1bad1f276
|
||
d1e15bdeb4c355e94
|
||
server_keyshare_seed: 360b0937f47d45f6123a4d8f0d0c0814b6120d840ebb8bc
|
||
5b4f6b62df07f78c2
|
||
masking_key: caecc6ccb4cae27cb54d8f3a1af1bac52a3d53107ce08497cdd362b1
|
||
992e4e5e
|
||
KE1: 0396875da2b4f7749bba411513aea02dc514a48d169d8a9531bd61d3af3fa9ba
|
||
ae42d4e61ed3f8d64cdd3b9d153343eca15b9b0d5e388232793c6376bd2d9cfd0a021
|
||
47a6583983cc9973b5082db5f5070890cb373d70f7ac1b41ed2305361009784
|
||
</pre><a href="#appendix-C.2.3.2-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="output-values-8">
|
||
<section id="appendix-C.2.3.3">
|
||
<h5 id="name-output-values-9">
|
||
<a href="#appendix-C.2.3.3" class="section-number selfRef">C.2.3.3. </a><a href="#name-output-values-9" class="section-name selfRef">Output Values</a>
|
||
</h5>
|
||
<div class="lang-test-vectors sourcecode" id="appendix-C.2.3.3-1">
|
||
<pre>
|
||
KE2: 0201198dcd13f9792eb75dcfa815f61b049abfe2e3e9456d4bbbceec5f442efd
|
||
049c035896a043e70f897d87180c543e7a063b83c1bb728fbd189c619e27b6e5a6fac
|
||
da65ce0a97b9085e7af07f61fd3fdd046d257cbf2183ce8766090b8041a8bf28d79dd
|
||
4c9031ddc75bb6ddb4c291e639937840e3d39fc0d5a3d6e7723c09f7945df485bcf9a
|
||
efe3fe82d149e84049e259bb5b33d6a2ff3b25e4bfb7eff0962821e10f6eeab2a7a42
|
||
0bf09da9b27a4639645622c46358de9cf7ae813055ae2d12023f82bbb24e75b8683fd
|
||
13b843cd566efae996cd0016cffdcc24ee2bc937d026f80144878749a69565b433c10
|
||
40aff67e94f79345de888a877422b9bbe21ec329
|
||
</pre><a href="#appendix-C.2.3.3-1" class="pilcrow">¶</a>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
<div id="acknowledgments">
|
||
<section id="appendix-D">
|
||
<h2 id="name-acknowledgments">
|
||
<a href="#name-acknowledgments" class="section-name selfRef">Acknowledgments</a>
|
||
</h2>
|
||
<p id="appendix-D-1">We are indebted to the OPAQUE reviewers during CFRG's aPAKE selection
|
||
process, particularly <span class="contact-name">Julia Hesse</span> and <span class="contact-name">Bjorn Tackmann</span>. This document has benefited from comments by
|
||
multiple people. Special thanks to <span class="contact-name">Richard Barnes</span>,
|
||
<span class="contact-name">Dan Brown</span>, <span class="contact-name">Matt Campagna</span>,
|
||
<span class="contact-name">Eric Crockett</span>, <span class="contact-name">Paul Grubbs</span>,
|
||
<span class="contact-name">Fredrik Kuivinen</span>, <span class="contact-name">Stefan Marsiske</span>, <span class="contact-name">Payman Mohassel</span>, <span class="contact-name">Marta Mularczyk</span>, <span class="contact-name">Jason Resch</span>,
|
||
<span class="contact-name">Greg Rubin</span>, and <span class="contact-name">Nick Sullivan</span>. <span class="contact-name">Hugo Krawczyk</span> wishes to thank his
|
||
OPAQUE co-authors <span class="contact-name">Stas Jarecki</span> and <span class="contact-name">Jiayu Xu</span>, without whom this work would have not been
|
||
possible.<a href="#appendix-D-1" class="pilcrow">¶</a></p>
|
||
</section>
|
||
</div>
|
||
<div id="authors-addresses">
|
||
<section id="appendix-E">
|
||
<h2 id="name-authors-addresses">
|
||
<a href="#name-authors-addresses" class="section-name selfRef">Authors' Addresses</a>
|
||
</h2>
|
||
<address class="vcard">
|
||
<div dir="auto" class="left"><span class="fn nameRole">Daniel Bourdrez</span></div>
|
||
<div class="email">
|
||
<span>Email:</span>
|
||
<a href="mailto:d@bytema.re" class="email">d@bytema.re</a>
|
||
</div>
|
||
</address>
|
||
<address class="vcard">
|
||
<div dir="auto" class="left"><span class="fn nameRole">Hugo Krawczyk</span></div>
|
||
<div dir="auto" class="left"><span class="org">AWS</span></div>
|
||
<div class="email">
|
||
<span>Email:</span>
|
||
<a href="mailto:hugokraw@gmail.com" class="email">hugokraw@gmail.com</a>
|
||
</div>
|
||
</address>
|
||
<address class="vcard">
|
||
<div dir="auto" class="left"><span class="fn nameRole">Kevin Lewi</span></div>
|
||
<div dir="auto" class="left"><span class="org">Meta</span></div>
|
||
<div class="email">
|
||
<span>Email:</span>
|
||
<a href="mailto:lewi.kevin.k@gmail.com" class="email">lewi.kevin.k@gmail.com</a>
|
||
</div>
|
||
</address>
|
||
<address class="vcard">
|
||
<div dir="auto" class="left"><span class="fn nameRole">Christopher A. Wood</span></div>
|
||
<div dir="auto" class="left"><span class="org">Cloudflare, Inc.</span></div>
|
||
<div class="email">
|
||
<span>Email:</span>
|
||
<a href="mailto:caw@heapingbits.net" class="email">caw@heapingbits.net</a>
|
||
</div>
|
||
</address>
|
||
</section>
|
||
</div>
|
||
<script>const toc = document.getElementById("toc");
|
||
toc.querySelector("h2").addEventListener("click", e => {
|
||
toc.classList.toggle("active");
|
||
});
|
||
toc.querySelector("nav").addEventListener("click", e => {
|
||
toc.classList.remove("active");
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|