Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Added] CreateUserSeed and CreateAccountSeed so these can be generated #434

Merged
merged 2 commits into from
Feb 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions src/NATS.Client/NKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// limitations under the License.
using NATS.Client.NaCl;
using System;
using System.IO;
using System.Text;

namespace NATS.Client
{
Expand Down Expand Up @@ -231,8 +233,7 @@ public static void Wipe(string src)
src.Remove(0);
}


private static byte[] DecodeSeed(byte[] raw)
internal static byte[] DecodeSeed(byte[] raw)
{
// Need to do the reverse here to get back to internal representation.
byte b1 = (byte)(raw[0] & 248); // 248 = 11111000
Expand Down Expand Up @@ -261,7 +262,7 @@ private static byte[] DecodeSeed(byte[] raw)
}
}

private static byte[] DecodeSeed(string src)
internal static byte[] DecodeSeed(string src)
{
return DecodeSeed(Nkeys.Decode(src));
}
Expand All @@ -271,7 +272,7 @@ private static byte[] DecodeSeed(string src)
/// </summary>
/// <param name="seed"></param>
/// <returns>A NATS Ed25519 Keypair</returns>
static public NkeyPair FromSeed(string seed)
public static NkeyPair FromSeed(string seed)
{
byte[] userSeed = DecodeSeed(seed);
try
Expand All @@ -284,5 +285,68 @@ static public NkeyPair FromSeed(string seed)
Wipe(ref userSeed);
}
}

internal static string EncodeSeed(byte prefixbyte, byte[] src)
{
if (!IsValidPublicPrefixByte(prefixbyte))
throw new NATSException("Invalid prefix");

if (src.Length != 32)
throw new NATSException("Invalid seed size");

// In order to make this human printable for both bytes, we need to do a little
// bit manipulation to setup for base32 encoding which takes 5 bits at a time.
byte b1 = (byte) (PrefixByteSeed | (prefixbyte >> 5));
byte b2 = (byte) ((prefixbyte & 31) << 3); // 31 = 00011111

MemoryStream stream = new MemoryStream();
stream.WriteByte(b1);
stream.WriteByte(b2);

// write payload
stream.Write(src, 0, src.Length);

// Calculate and write crc16 checksum
byte[] checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray()));
stream.Write(checksum, 0, checksum.Length);

return Base32.Encode(stream.ToArray());
}

private static string CreateSeed(byte prefixbyte) {
byte[] rawSeed = new byte[32];

Random rnd = new Random();
rnd.NextBytes(rawSeed);

return EncodeSeed(prefixbyte, rawSeed);
}

/// <summary>
/// Creates a private user seed String.
/// </summary>
/// <returns>A NATS Ed25519 User Seed</returns>
public static string CreateUserSeed()
{
return CreateSeed(PrefixByteUser);
}

/// <summary>
/// Creates a private account seed String.
/// </summary>
/// <returns>A NATS Ed25519 Account Seed</returns>
public static string CreateAccountSeed()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add the others for completeness in case someone want to write a utility out of this... wdyt?

eg.

public static string CreateOperatorSeed();
public static string CreateServerSeed();
public static string CreateClusterSeed();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will add CreateOperatorSeed. Server and Cluster are not used.

{
return CreateSeed(PrefixByteAccount);
}

/// <summary>
/// Creates a private operator seed String.
/// </summary>
/// <returns>A NATS Ed25519 Operator Seed</returns>
public static string CreateOperatorSeed()
{
return CreateSeed(PrefixByteOperator);
}
}
}
62 changes: 62 additions & 0 deletions src/Tests/UnitTests/TestNkeys.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2021-2021 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using NATS.Client;
using Xunit;

namespace UnitTests
{
#pragma warning disable CS0618
public class TestNkeys
{
[Fact]
public void TestNKEYEncodeDecode()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add seeds created by CreateUserSeed, CreateAccountSeed, etc...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

already have TestNKEYCreateUserSeed and TestNKEYCreateAccountSeed further down, will add the operator one

{
byte[] a = new Byte[32];
byte[] b = Nkeys.DecodeSeed( Nkeys.EncodeSeed(20 << 3, a));
Assert.Equal(a, b);

Random rnd = new Random();
rnd.NextBytes(a);
b = Nkeys.DecodeSeed( Nkeys.EncodeSeed(20 << 3, a));
Assert.Equal(a, b);
}

[Fact]
public void TestNKEYCreateUserSeed()
{
string user = Nkeys.CreateUserSeed();
Assert.NotEmpty(user);
Assert.NotNull(Nkeys.FromSeed(user));
}

[Fact]
public void TestNKEYCreateAccountSeed()
{
string acc = Nkeys.CreateAccountSeed();
Assert.NotEmpty(acc);
Assert.NotNull(Nkeys.FromSeed(acc));
}

[Fact]
public void TestNKEYCreateOperatorSeed()
{
string op = Nkeys.CreateOperatorSeed();
Assert.NotEmpty(op);
Assert.NotNull(Nkeys.FromSeed(op));
}
}

#pragma warning restore CS0618
}