releasing key guide under CC 4.0 BY-SA

This commit is contained in:
Brent S. 2023-09-04 01:40:39 -04:00
parent b38739f960
commit 4b1cfd0c50
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
32 changed files with 378 additions and 256 deletions

3
.gitignore vendored
View File

@ -30,6 +30,9 @@
*.test *.test
!*test.go !*test.go
# Junk for figuring stuff out
/poc/
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out

View File

@ -3,3 +3,5 @@
OpenSSH key parsing, generation, etc. library for Golang. OpenSSH key parsing, generation, etc. library for Golang.
Supports newer "proprietary" key type formatting ("OpenSSH v1"). Supports newer "proprietary" key type formatting ("OpenSSH v1").
**WORK IN PROGRESS**

View File

@ -15,6 +15,12 @@ Last updated {localdatetime}
:source-highlighter: rouge :source-highlighter: rouge
:docinfo: shared :docinfo: shared
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
== Purpose == Purpose
This document attempts to present a much more detailed, thorough, and easily-understood form of the key formats used by OpenSSH. The extent of those formats' canonical documentation is https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key[the OpenSSH source tree's `PROTOCOL.key`^], which is a little lacking. This document attempts to present a much more detailed, thorough, and easily-understood form of the key formats used by OpenSSH. The extent of those formats' canonical documentation is https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key[the OpenSSH source tree's `PROTOCOL.key`^], which is a little lacking.
@ -62,3 +68,15 @@ All public keys in v1 continue to use the same packed binary format as <<public_
include::rsa/main.adoc[] include::rsa/main.adoc[]
include::ed25519/main.adoc[] include::ed25519/main.adoc[]
== Further Information
++++
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a><br />
<span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/Text" property="dct:title" rel="dct:type">OpenSSH Key Structure Guide</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://r00t2.io/" property="cc:attributionName" rel="cc:attributionURL">Brent Saner</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.<br />
<br />
++++
You are free to use, distribute, modify, redistribute, use for commercial purposes, etc. with very few restrictions; please see http://creativecommons.org/licenses/by-sa/4.0/[the license summary^] and https://creativecommons.org/licenses/by-sa/4.0/legalcode[full license^] for further details.

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.17"> <meta name="generator" content="Asciidoctor 2.0.20">
<meta name="author" content="brent saner &lt;bts@square-r00t.net&gt;, https://r00t2.io"> <meta name="author" content="brent saner &lt;bts@square-r00t.net&gt;, https://r00t2.io">
<title>OpenSSH Key Structure Guide</title> <title>OpenSSH Key Structure Guide</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
@ -85,10 +85,10 @@ code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em} ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0} ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle} ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc} ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold} dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em} dl dd{margin-bottom:1.25em}
@ -209,13 +209,10 @@ table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere} .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px} .exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px} .sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} .exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em} .literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}} @media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}} @media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
@ -394,7 +391,7 @@ b.conum *{color:inherit!important}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em} h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem} p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem} p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc} .exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
@ -439,217 +436,116 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
<style> <style>
pre.rouge table td { padding: 5px; } pre.rouge table td { padding: 5px; }
pre.rouge table pre { margin: 0; } pre.rouge table pre { margin: 0; }
pre.rouge .cm { pre.rouge, pre.rouge .w {
color: #999988; color: #24292f;
font-style: italic; background-color: #f6f8fa;
} }
pre.rouge .cp { pre.rouge .k, pre.rouge .kd, pre.rouge .kn, pre.rouge .kp, pre.rouge .kr, pre.rouge .kt, pre.rouge .kv {
color: #999999; color: #cf222e;
font-weight: bold;
}
pre.rouge .c1 {
color: #999988;
font-style: italic;
}
pre.rouge .cs {
color: #999999;
font-weight: bold;
font-style: italic;
}
pre.rouge .c, pre.rouge .ch, pre.rouge .cd, pre.rouge .cpf {
color: #999988;
font-style: italic;
}
pre.rouge .err {
color: #a61717;
background-color: #e3d2d2;
}
pre.rouge .gd {
color: #000000;
background-color: #ffdddd;
}
pre.rouge .ge {
color: #000000;
font-style: italic;
} }
pre.rouge .gr { pre.rouge .gr {
color: #aa0000; color: #f6f8fa;
} }
pre.rouge .gh { pre.rouge .gd {
color: #999999; color: #82071e;
background-color: #ffebe9;
}
pre.rouge .nb {
color: #953800;
}
pre.rouge .nc {
color: #953800;
}
pre.rouge .no {
color: #953800;
}
pre.rouge .nn {
color: #953800;
}
pre.rouge .sr {
color: #116329;
}
pre.rouge .na {
color: #116329;
}
pre.rouge .nt {
color: #116329;
} }
pre.rouge .gi { pre.rouge .gi {
color: #000000; color: #116329;
background-color: #ddffdd; background-color: #dafbe1;
} }
pre.rouge .go { pre.rouge .kc {
color: #888888; color: #0550ae;
} }
pre.rouge .gp { pre.rouge .l, pre.rouge .ld, pre.rouge .m, pre.rouge .mb, pre.rouge .mf, pre.rouge .mh, pre.rouge .mi, pre.rouge .il, pre.rouge .mo, pre.rouge .mx {
color: #555555; color: #0550ae;
} }
pre.rouge .gs { pre.rouge .sb {
color: #0550ae;
}
pre.rouge .bp {
color: #0550ae;
}
pre.rouge .ne {
color: #0550ae;
}
pre.rouge .nl {
color: #0550ae;
}
pre.rouge .py {
color: #0550ae;
}
pre.rouge .nv, pre.rouge .vc, pre.rouge .vg, pre.rouge .vi, pre.rouge .vm {
color: #0550ae;
}
pre.rouge .o, pre.rouge .ow {
color: #0550ae;
}
pre.rouge .gh {
color: #0550ae;
font-weight: bold; font-weight: bold;
} }
pre.rouge .gu { pre.rouge .gu {
color: #aaaaaa; color: #0550ae;
}
pre.rouge .gt {
color: #aa0000;
}
pre.rouge .kc {
color: #000000;
font-weight: bold; font-weight: bold;
} }
pre.rouge .kd { pre.rouge .s, pre.rouge .sa, pre.rouge .sc, pre.rouge .dl, pre.rouge .sd, pre.rouge .s2, pre.rouge .se, pre.rouge .sh, pre.rouge .sx, pre.rouge .s1, pre.rouge .ss {
color: #000000; color: #0a3069;
font-weight: bold;
}
pre.rouge .kn {
color: #000000;
font-weight: bold;
}
pre.rouge .kp {
color: #000000;
font-weight: bold;
}
pre.rouge .kr {
color: #000000;
font-weight: bold;
}
pre.rouge .kt {
color: #445588;
font-weight: bold;
}
pre.rouge .k, pre.rouge .kv {
color: #000000;
font-weight: bold;
}
pre.rouge .mf {
color: #009999;
}
pre.rouge .mh {
color: #009999;
}
pre.rouge .il {
color: #009999;
}
pre.rouge .mi {
color: #009999;
}
pre.rouge .mo {
color: #009999;
}
pre.rouge .m, pre.rouge .mb, pre.rouge .mx {
color: #009999;
}
pre.rouge .sa {
color: #000000;
font-weight: bold;
}
pre.rouge .sb {
color: #d14;
}
pre.rouge .sc {
color: #d14;
}
pre.rouge .sd {
color: #d14;
}
pre.rouge .s2 {
color: #d14;
}
pre.rouge .se {
color: #d14;
}
pre.rouge .sh {
color: #d14;
}
pre.rouge .si {
color: #d14;
}
pre.rouge .sx {
color: #d14;
}
pre.rouge .sr {
color: #009926;
}
pre.rouge .s1 {
color: #d14;
}
pre.rouge .ss {
color: #990073;
}
pre.rouge .s, pre.rouge .dl {
color: #d14;
}
pre.rouge .na {
color: #008080;
}
pre.rouge .bp {
color: #999999;
}
pre.rouge .nb {
color: #0086B3;
}
pre.rouge .nc {
color: #445588;
font-weight: bold;
}
pre.rouge .no {
color: #008080;
} }
pre.rouge .nd { pre.rouge .nd {
color: #3c5d5d; color: #8250df;
font-weight: bold;
}
pre.rouge .ni {
color: #800080;
}
pre.rouge .ne {
color: #990000;
font-weight: bold;
} }
pre.rouge .nf, pre.rouge .fm { pre.rouge .nf, pre.rouge .fm {
color: #990000; color: #8250df;
}
pre.rouge .err {
color: #f6f8fa;
background-color: #82071e;
}
pre.rouge .c, pre.rouge .ch, pre.rouge .cd, pre.rouge .cm, pre.rouge .cp, pre.rouge .cpf, pre.rouge .c1, pre.rouge .cs {
color: #6e7781;
}
pre.rouge .gl {
color: #6e7781;
}
pre.rouge .gt {
color: #6e7781;
}
pre.rouge .ni {
color: #24292f;
}
pre.rouge .si {
color: #24292f;
}
pre.rouge .ge {
color: #24292f;
font-style: italic;
}
pre.rouge .gs {
color: #24292f;
font-weight: bold; font-weight: bold;
} }
pre.rouge .nl {
color: #990000;
font-weight: bold;
}
pre.rouge .nn {
color: #555555;
}
pre.rouge .nt {
color: #000080;
}
pre.rouge .vc {
color: #008080;
}
pre.rouge .vg {
color: #008080;
}
pre.rouge .vi {
color: #008080;
}
pre.rouge .nv, pre.rouge .vm {
color: #008080;
}
pre.rouge .ow {
color: #000000;
font-weight: bold;
}
pre.rouge .o {
color: #000000;
font-weight: bold;
}
pre.rouge .w {
color: #bbbbbb;
}
pre.rouge {
background-color: #f8f8f8;
}
</style> </style>
<!-- https://stackoverflow.com/a/34481639 --> <!-- https://stackoverflow.com/a/34481639 -->
<!-- Generate a nice TOC --> <!-- Generate a nice TOC -->
@ -734,7 +630,7 @@ pre.rouge {
<h1>OpenSSH Key Structure Guide</h1> <h1>OpenSSH Key Structure Guide</h1>
<div class="details"> <div class="details">
<span id="author" class="author">brent saner &lt;bts@square-r00t.net&gt;, https://r00t2.io</span><br> <span id="author" class="author">brent saner &lt;bts@square-r00t.net&gt;, https://r00t2.io</span><br>
<span id="revdate">Last updated 2022-04-29 16:31:13 -0400</span> <span id="revdate">Last updated 2023-09-04 01:40:40 -0400</span>
</div> </div>
<div id="toc" class="toc2"> <div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div> <div id="toctitle">Table of Contents</div>
@ -825,6 +721,7 @@ pre.rouge {
</li> </li>
</ul> </ul>
</li> </li>
<li><a href="#further_information">4. Further Information</a></li>
</ul> </ul>
</div> </div>
</div> </div>
@ -2945,6 +2842,19 @@ dCXGDaRlL924VVCYUytRvu7ilZ+dtc9aCQUFJyDF3iXyxN2H68x7teo9e8vqzGtzLkw5KV
</div> </div>
</div> </div>
</div> </div>
<div class="sect1">
<h2 id="further_information"><a class="link" href="#further_information">4. Further Information</a></h2>
<div class="sectionbody">
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" />
</a><br />
<span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/Text" property="dct:title" rel="dct:type">OpenSSH Key Structure Guide</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://r00t2.io/" property="cc:attributionName" rel="cc:attributionURL">Brent Saner</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.<br />
<br />
<div class="paragraph">
<p>You are free to use, distribute, modify, redistribute, use for commercial purposes, etc. with very few restrictions; please see <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener">the license summary</a> and <a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode" target="_blank" rel="noopener">full license</a> for further details.</p>
</div>
</div>
</div>
</div> </div>
<div id="footnotes"> <div id="footnotes">
<hr> <hr>
@ -2963,7 +2873,7 @@ dCXGDaRlL924VVCYUytRvu7ilZ+dtc9aCQUFJyDF3iXyxN2H68x7teo9e8vqzGtzLkw5KV
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2022-03-07 03:36:15 -0500 Last updated 2023-09-04 01:31:56 -0400
</div> </div>
</div> </div>
</body> </body>

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
=== ED25519 === ED25519
ED25519footnote:[https://datatracker.ietf.org/doc/html/rfc8709] is a relatively somewhat new OpenSSH key algorithm. It has numerous benefits over e.g. RSA, including: ED25519footnote:[https://datatracker.ietf.org/doc/html/rfc8709] is a relatively somewhat new OpenSSH key algorithm. It has numerous benefits over e.g. RSA, including:

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
===== Legacy ===== Legacy
[NOTE] [NOTE]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
==== Private ==== Private
include::legacy/main.adoc[] include::legacy/main.adoc[]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
===== v1 (Encrypted) ===== v1 (Encrypted)
[TIP] [TIP]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
include::plain.adoc[] include::plain.adoc[]
include::encrypted.adoc[] include::encrypted.adoc[]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
===== v1 (Plain) ===== v1 (Plain)
[TIP] [TIP]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
==== Public ==== Public
===== Structure ===== Structure

View File

@ -1,5 +1,11 @@
package main package main
/*
* This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
* To view a copy of this license, visit
* http://creativecommons.org/licenses/by-sa/4.0/.
*/
import ( import (
"crypto" "crypto"
"crypto/aes" "crypto/aes"

View File

@ -1,5 +1,11 @@
package main package main
/*
* This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
* To view a copy of this license, visit
* http://creativecommons.org/licenses/by-sa/4.0/.
*/
import ( import (
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
=== RSA === RSA
RSAfootnote:[https://datatracker.ietf.org/doc/html/rfc8017] is a widely-supported PKI system. It is ubiquitous, but it is recommended to use newer systems (e.g. ED25519) for OpenSSH if all clients and destinations support it. RSAfootnote:[https://datatracker.ietf.org/doc/html/rfc8017] is a widely-supported PKI system. It is ubiquitous, but it is recommended to use newer systems (e.g. ED25519) for OpenSSH if all clients and destinations support it.

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
===== Legacy (Encrypted) ===== Legacy (Encrypted)
[id=struct_rsa_crypt_legacy] [id=struct_rsa_crypt_legacy]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
include::plain.adoc[] include::plain.adoc[]
include::encrypted.adoc[] include::encrypted.adoc[]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
===== Legacy (Plain) ===== Legacy (Plain)
[id=struct_rsa_plain_legacy] [id=struct_rsa_plain_legacy]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
==== Private ==== Private
include::legacy/main.adoc[] include::legacy/main.adoc[]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
===== v1 (Encrypted) ===== v1 (Encrypted)
[TIP] [TIP]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
include::plain.adoc[] include::plain.adoc[]
include::encrypted.adoc[] include::encrypted.adoc[]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
===== v1 (Plain) ===== v1 (Plain)
[TIP] [TIP]

View File

@ -1,3 +1,9 @@
////
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/4.0/.
////
==== Public ==== Public
===== Structure ===== Structure

View File

@ -1,3 +1,13 @@
######################################################################################################
# This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. #
# To view a copy of this license, visit #
# http://creativecommons.org/licenses/by-sa/4.0/. #
######################################################################################################
= NOTES =
This document is largely just a dump of "further reading" resources.
https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
canonical: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD canonical: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD
https://peterlyons.com/problog/2017/12/openssh-ed25519-private-key-file-format/ https://peterlyons.com/problog/2017/12/openssh-ed25519-private-key-file-format/
@ -48,4 +58,4 @@ https://github.com/openssh/openssh-portable/blob/master/authfile.c
sshkey_save_private_blob (~L56) sshkey_save_private_blob (~L56)
https://github.com/openssh/openssh-portable/blob/master/ssh-keygen.c https://github.com/openssh/openssh-portable/blob/master/ssh-keygen.c
funcs: funcs:
main (~L3145; ~L3673 onwards for key generation) main (~L3145; ~L3673 onwards for key generation)

View File

@ -0,0 +1,3 @@
TODO
I need to look further into the aes128-gcm@openssh.com variant to see if this is valid.

View File

@ -0,0 +1,3 @@
TODO
I need to look further into the aes256-gcm@openssh.com variant to see if this is valid.

View File

@ -1 +1,14 @@
TODO TODO
I need to fork out the chacha20-poly1305 pkg from golang x-stdlib
(
https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305
https://cs.opensource.google/go/x/crypto/+/master:chacha20poly1305/
https://github.com/golang/go/issues/36646
)
because they explicitly do NOT support the chacha20-poly1305 OpenSSH variant (chacha20-poly1305@openssh.com)
(https://github.com/golang/go/issues/36646#issue-552055939
"and there is exactly one widely used (or otherwise) composition:
ChaCha20Poly1305 as implemented by x/crypto/chacha20poly1305 (or by SSH in their weird variant)"
sidenote, this is the same guy that decided it would be a good idea to deprecate golang x-stdlib gpg).

View File

@ -1,5 +1,6 @@
package poly1305 package poly1305
const ( const (
Name string = "chacha20-poly1305@openssh.com" Name string = "chacha20-poly1305@openssh.com"
BlockSize int = 8
) )

View File

@ -4,8 +4,7 @@ import (
`bytes` `bytes`
`io` `io`
`r00t2.io/sshkeys/cipher/aes` `r00t2.io/cc20p1305ssh`
`r00t2.io/sshkeys/cipher/aes/aes128`
`r00t2.io/sshkeys/internal` `r00t2.io/sshkeys/internal`
) )
@ -39,7 +38,7 @@ func (c *Cipher) NameBytes() (name []byte) {
// BlockSize returns the blocksize of this Cipher. // BlockSize returns the blocksize of this Cipher.
func (c *Cipher) BlockSize() (size int) { func (c *Cipher) BlockSize() (size int) {
size = aes.BlockSize size = BlockSize
return return
} }
@ -47,7 +46,7 @@ func (c *Cipher) BlockSize() (size int) {
// KdfKeySize returns the target key length from KDF to use with this Cipher. // KdfKeySize returns the target key length from KDF to use with this Cipher.
func (c *Cipher) KdfKeySize() (size int) { func (c *Cipher) KdfKeySize() (size int) {
size = aes128.KeySize size = cc20p1305ssh.KeySize
return return
} }

View File

@ -1,5 +1,22 @@
package poly1305 package poly1305
/*
Cipher is a ChaCha20-Poly1305 (OpenSSH variant) cipher.Cipher.
In the OpenSSH variant (for *key* encryption), only the first
32 bytes is used from the 64-byte key as generated from ChaCha20.
It then proceeds per https://datatracker.ietf.org/doc/html/rfc8439#section-2.8
except:
* The nonce used is a constant of 16 zero bytes
* There is no additional authenticated data
* The Poly1305 authentication tag is generated via a message
that consists *only* of the ciphertext.
In other words, OpenSSH does *not* add padding or
encode message lengths to generate the Poly1305
authentication tag.
*/
type Cipher struct { type Cipher struct {
Key []byte Key []byte
} }

6
cipher/null/consts.go Normal file
View File

@ -0,0 +1,6 @@
package null
const (
Name string = ""
BlockSize int = 8
)

View File

@ -1,17 +1,26 @@
package null package null
import ( import (
`bytes` "bytes"
`io`
`r00t2.io/sshkeys/cipher/aes` `r00t2.io/sshkeys/cipher`
`r00t2.io/sshkeys/cipher/aes/aes128` "r00t2.io/sshkeys/internal"
`r00t2.io/sshkeys/internal`
) )
/*
Setup populates a Cipher from a key.
This is basically a no-op as null.Cipher does not offer any encryption, so there's no setup necessary.
*/
func (c *Cipher) Setup(key []byte) (err error) { func (c *Cipher) Setup(key []byte) (err error) {
// TODO if c == nil {
*c = Cipher{}
}
if err = c.keyChk(); err != nil {
return
}
return return
} }
@ -39,21 +48,26 @@ func (c *Cipher) NameBytes() (name []byte) {
// BlockSize returns the blocksize of this Cipher. // BlockSize returns the blocksize of this Cipher.
func (c *Cipher) BlockSize() (size int) { func (c *Cipher) BlockSize() (size int) {
size = aes.BlockSize size = BlockSize
return
}
// KdfKeySize returns the target key length from KDF to use with this Cipher.
func (c *Cipher) KdfKeySize() (size int) {
size = aes128.KeySize
return return
} }
/* /*
Encrypt encrypts data (a string, []byte, byte, *bytes.Buffer, or *bytes.Reader) to the *bytes.Reader encrypted. KdfKeySize returns the target key length from KDF to use with this Cipher.
Because this function is only here for interface compat, it always returns 0
(as a Null cipher uses no KDF).
*/
func (c *Cipher) KdfKeySize() (size int) {
size = 0
return
}
/*
Encrypt "encrypts" data (a string, []byte, byte, *bytes.Buffer, or *bytes.Reader) to the *bytes.Reader encrypted.
NOTE: Padding IS applied automatically. NOTE: Padding IS applied automatically.
@ -61,31 +75,15 @@ func (c *Cipher) KdfKeySize() (size int) {
It is up to the caller to consume the buffer as desired beforehand or isolate to a specific sub-buffer beforehand to pass to Cipher.Encrypt. It is up to the caller to consume the buffer as desired beforehand or isolate to a specific sub-buffer beforehand to pass to Cipher.Encrypt.
NOTE: If data is a *bytes.Reader, ALL bytes WILL be consumed. NOTE: If data is a *bytes.Reader, ALL bytes WILL be consumed.
NOTE: No actual encryption takes place, only padding.
*/ */
func (c *Cipher) Encrypt(data interface{}) (encrypted *bytes.Reader, err error) { func (c *Cipher) Encrypt(data interface{}) (encrypted *bytes.Reader, err error) {
var b []byte if encrypted, err = c.Pad(data); err != nil {
var cryptDst []byte
var padded *bytes.Reader
if b, err = internal.SerializeData(data); err != nil {
return return
} }
if padded, err = c.Pad(b); err != nil {
return
}
b = make([]byte, padded.Len())
if b, err = io.ReadAll(padded); err != nil {
return
}
cryptDst = make([]byte, len(b))
// TODO
_ = cryptDst
return return
} }
@ -125,17 +123,38 @@ func (c *Cipher) AllocateEncrypt(data interface{}) (encrypted *bytes.Reader, err
} }
/* /*
Pad will pad data (a string, []byte, byte, or *bytes.Buffer) to the Cipher.BlockSize (if necessary). Pad will pad data (a string, []byte, byte, *bytes.Buffer, *bytes.Reader) to the Cipher.BlockSize. The resulting padded *bytes.Reader is returned.
The resulting padded buffer is returned.
NOTE: If data is a *bytes.Buffer, no bytes will be consumed -- the bytes are taken in entirety without consuming them (Buffer.Bytes()). NOTE: If data is a *bytes.Buffer, no bytes will be consumed -- the bytes are taken in entirety without consuming them (Buffer.Bytes()).
It is up to the caller to consume the buffer as desired beforehand or isolate to a specific sub-buffer beforehand to pass to Cipher.Pad. It is up to the caller to consume the buffer as desired beforehand or isolate to a specific sub-buffer beforehand to pass to Pad.
NOTE: If data is a *bytes.Reader, ALL bytes WILL be consumed. NOTE: If data is a *bytes.Reader, ALL bytes WILL be consumed.
*/ */
func (c *Cipher) Pad(data interface{}) (paddedBuf *bytes.Reader, err error) { func (c *Cipher) Pad(data interface{}) (paddedBuf *bytes.Reader, err error) {
// TODO var b []byte
var padNum int
var pad []byte
var buf *bytes.Buffer
if err = c.keyChk(); err != nil {
return
}
if b, err = internal.UnpackBytes(data); err != nil {
return
}
buf = bytes.NewBuffer(b)
for padIdx := 1; (buf.Len() % BlockSize) != 0; padIdx++ {
padNum = padIdx & cipher.PadMod
pad = []byte{byte(uint32(padNum))}
if _, err = buf.Write(pad); err != nil {
return
}
}
return return
} }
@ -152,17 +171,13 @@ func (c *Cipher) Pad(data interface{}) (paddedBuf *bytes.Reader, err error) {
*/ */
func (c *Cipher) Decrypt(data interface{}) (decrypted *bytes.Reader, err error) { func (c *Cipher) Decrypt(data interface{}) (decrypted *bytes.Reader, err error) {
var b []byte var plain []byte
var decryptDst []byte
if b, err = internal.SerializeData(data); err != nil { if plain, err = internal.SerializeData(data); err != nil {
return return
} }
decryptDst = make([]byte, len(b)) decrypted = bytes.NewReader(plain)
// TODO
_ = decryptDst
return return
} }
@ -195,11 +210,21 @@ func (c *Cipher) AllocatedDecrypt(data interface{}) (decrypted *bytes.Reader, er
/* /*
IsPlain indicates if this Cipher is a plain/null encryption (cipher.null.Null). IsPlain indicates if this Cipher is a plain/null encryption (cipher.null.Null).
It will always return false. It is included for interface compatability. It will always return true. It is included for interface compatability.
*/ */
func (c *Cipher) IsPlain() (plain bool) { func (c *Cipher) IsPlain() (plain bool) {
plain = false plain = true
return
}
// keyChk is more or less a no-op but provides some basic sanity checking.
func (c *Cipher) keyChk() (err error) {
if c == nil {
*c = Cipher{}
}
return return
} }

4
cipher/null/types.go Normal file
View File

@ -0,0 +1,4 @@
package null
// Cipher is a null (plaintext) cipher.Cipher.
type Cipher struct{}