A format/ssh/+test/rawkey.ha => format/ssh/+test/rawkey.ha +29 -0
@@ 0,0 1,29 @@
+use bufio;
+use bytes;
+use io;
+
+@test fn ed25519_rawkeys() void = {
+ const reader = bufio::fixed(testkey, io::mode::READ);
+ const sshkey = decodesshprivate(&reader)!;
+ defer sshprivkey_finish(&sshkey);
+ const private = decodeprivate(&sshkey)!;
+
+ let private = private: *ed25519key;
+ let copy = new_ed25519key();
+
+ let pubbuf = bufio::dynamic(io::mode::RDWR);
+ defer io::close(&pubbuf)!;
+ key_encoderawpub(private, &pubbuf)!;
+ io::seek(&pubbuf, 0, io::whence::SET)!;
+ key_decoderawpub(©, &pubbuf)!;
+
+ assert(bytes::equal(private.pubkey, copy.pubkey));
+
+ let privbuf = bufio::dynamic(io::mode::RDWR);
+ defer io::close(&privbuf)!;
+ key_encoderawpriv(private, &privbuf)!;
+ io::seek(&privbuf, 0, io::whence::SET)!;
+ key_decoderawpriv(©, &privbuf)!;
+
+ assert(bytes::equal(private.privkey, copy.privkey));
+};
M format/ssh/ed25519.ha => format/ssh/ed25519.ha +46 -0
@@ 14,6 14,10 @@ const ed25519_vtable: key_vtable = key_vtable {
decodepub = &ed25519_decodepub,
decodepriv = &ed25519_decodepriv,
encodepub = &ed25519_encodepub,
+ encoderawpub = &ed25519_encoderawpubfunc,
+ decoderawpub = &ed25519_decoderawpubfunc,
+ encoderawpriv = &ed25519_encoderawprivfunc,
+ decoderawpriv = &ed25519_decoderawprivfunc,
sign = &ed25519_sign,
verify = &ed25519_verify,
finish = &ed25519_finish,
@@ 60,6 64,48 @@ fn ed25519_encodepub(key: *const key, sink: io::handle) (void | io::error) = {
writeslice(sink, key.pubkey)?;
};
+fn ed25519_encoderawpubfunc(
+ key: *const key,
+ sink: io::handle
+) (void | io::error) = {
+ let key = key: *ed25519key;
+ io::writeall(sink, key.pubkey)?;
+};
+
+fn ed25519_decoderawpubfunc(key: *key, src: io::handle) (void | error) = {
+ let key = key: *ed25519key;
+ match (io::readall(src, key.pubkey)?) {
+ case io::EOF =>
+ return invalid;
+ case let n: size =>
+ if (n != ed25519::PUBKEYSZ) {
+ return n: io::underread;
+ };
+ };
+};
+
+fn ed25519_encoderawprivfunc(
+ key: *const key,
+ sink: io::handle
+) (void | io::error) = {
+ let key = key: *ed25519key;
+ io::writeall(sink, key.privkey)?;
+};
+
+fn ed25519_decoderawprivfunc(key: *key, src: io::handle) (void | error) = {
+ let key = key: *ed25519key;
+ match (io::readall(src, key.privkey)?) {
+ case io::EOF =>
+ bytes::zero(key.privkey);
+ return 0: io::underread;
+ case let n: size =>
+ if (n != ed25519::PRIVKEYSZ) {
+ bytes::zero(key.privkey);
+ return n: io::underread;
+ };
+ };
+};
+
fn ed25519_sign(
key: *const key,
sink: io::handle,
M format/ssh/key.ha => format/ssh/key.ha +35 -1
@@ 8,6 8,10 @@ use io;
export type decodepubfunc = fn(key: *key, buf: io::handle) (void | error);
export type decodeprivfunc = fn(key: *key, buf: io::handle) (void | error);
export type encodepubfunc = fn(key: *const key, sink: io::handle) (void | io::error);
+export type encoderawpubfunc = fn(key: *const key, sink: io::handle) (void | io::error);
+export type encoderawprivfunc = fn(key: *const key, sink: io::handle) (void | io::error);
+export type decoderawpubfunc = fn(key: *key, src: io::handle) (void | error);
+export type decoderawprivfunc = fn(key: *key, src: io::handle) (void | error);
export type signfunc = fn(key: *const key, sink: io::handle, msg: []u8) (void | io::error);
export type verifyfunc = fn(key: *const key, source: io::handle, msg: []u8) (void | error);
export type finishfunc = fn(key: *key) void;
@@ 17,6 21,10 @@ export type key_vtable = struct {
decodepub: *decodepubfunc,
decodepriv: *decodeprivfunc,
encodepub: *encodepubfunc,
+ encoderawpub: *encoderawpubfunc,
+ encoderawpriv: *encoderawprivfunc,
+ decoderawpub: *decoderawpubfunc,
+ decoderawpriv: *decoderawprivfunc,
sign: *signfunc,
verify: *verifyfunc,
finish: *finishfunc,
@@ 77,7 85,7 @@ export fn decodepublic(src: io::handle) (*key | error) = {
// Encodes a private key's public component using the SSH wire format, writing
// it into the given stream.
-export fn encode_pubkey(sink: io::handle, key: *const key) (void | io::error) = {
+export fn encode_pubkey(sink: io::handle, key: const *key) (void | io::error) = {
writestr(sink, keytype(key))?;
key.vtable.encodepub(key, sink)?;
};
@@ 94,6 102,28 @@ export fn encode_pubkeystr(sink: io::handle, key: *key) (void | io::error) = {
};
};
+// Encodes the raw private key part only, in such a way that it only may be
+// decoded using [[key_decodepriv]].
+export fn key_encoderawpriv(key: *key, sink: io::handle) (void | io::error) = {
+ return key.vtable.encoderawpriv(key, sink);
+};
+
+// Decode a raw private key encoded with [[key_encodepriv]].
+export fn key_decoderawpriv(key: *key, src: io::handle) (void | error) = {
+ return key.vtable.decoderawpriv(key, src);
+};
+
+// Encodes the raw public key part only, in such a way that it only may be
+// decoded using [[key_decodepub]].
+export fn key_encoderawpub(key: *key, sink: io::handle) (void | io::error) = {
+ return key.vtable.encoderawpub(key, sink);
+};
+
+// Decode a raw public key encoded with [[key_encodepub]].
+export fn key_decoderawpub(key: *key, src: io::handle) (void | error) = {
+ return key.vtable.decoderawpub(key, src);
+};
+
// Securely wipes data associated with a private key from memory and frees the
// key resource.
export fn key_free(key: *key) void = {
@@ 107,3 137,7 @@ export fn keytype(key: *key) const str = {
return key.vtable.keytype;
};
+// Returns the key comment.
+export fn key_comment(key: *key) str = {
+ return key.comment;
+};