Ed25519PublicKeyParameters
using Org.BouncyCastle.Math.EC.Rfc8032;
using Org.BouncyCastle.Utilities.IO;
using System;
using System.IO;
namespace Org.BouncyCastle.Crypto.Parameters
{
public sealed class Ed25519PublicKeyParameters : AsymmetricKeyParameter
{
public static readonly int KeySize = Ed25519.PublicKeySize;
private readonly Ed25519.PublicPoint m_publicPoint;
public Ed25519PublicKeyParameters(byte[] buf)
: this(Validate(buf), 0)
{
}
public Ed25519PublicKeyParameters(byte[] buf, int off)
: base(false)
{
m_publicPoint = Parse(buf, off);
}
public Ed25519PublicKeyParameters(ReadOnlySpan<byte> buf)
: base(false)
{
if (buf.Length != KeySize)
throw new ArgumentException("must have length " + KeySize.ToString(), "buf");
m_publicPoint = Parse(buf);
}
public unsafe Ed25519PublicKeyParameters(Stream input)
: base(false)
{
int keySize = KeySize;
Span<byte> span = new Span<byte>(stackalloc byte[(int)(uint)keySize], keySize);
if (KeySize != Streams.ReadFully(input, span))
throw new EndOfStreamException("EOF encountered in middle of Ed25519 public key");
m_publicPoint = Parse(span);
}
public Ed25519PublicKeyParameters(Ed25519.PublicPoint publicPoint)
: base(false)
{
if (publicPoint == null)
throw new ArgumentNullException("publicPoint");
m_publicPoint = publicPoint;
}
public void Encode(byte[] buf, int off)
{
Ed25519.EncodePublicPoint(m_publicPoint, buf, off);
}
public void Encode(Span<byte> buf)
{
Ed25519.EncodePublicPoint(m_publicPoint, buf);
}
public byte[] GetEncoded()
{
byte[] array = new byte[KeySize];
Encode(array, 0);
return array;
}
public bool Verify(Ed25519.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen, byte[] sig, int sigOff)
{
switch (algorithm) {
case Ed25519.Algorithm.Ed25519:
if (ctx != null)
throw new ArgumentOutOfRangeException("ctx");
return Ed25519.Verify(sig, sigOff, m_publicPoint, msg, msgOff, msgLen);
case Ed25519.Algorithm.Ed25519ctx:
if (ctx == null)
throw new ArgumentNullException("ctx");
if (ctx.Length > 255)
throw new ArgumentOutOfRangeException("ctx");
return Ed25519.Verify(sig, sigOff, m_publicPoint, ctx, msg, msgOff, msgLen);
case Ed25519.Algorithm.Ed25519ph:
if (ctx == null)
throw new ArgumentNullException("ctx");
if (ctx.Length > 255)
throw new ArgumentOutOfRangeException("ctx");
if (Ed25519.PrehashSize != msgLen)
throw new ArgumentOutOfRangeException("msgLen");
return Ed25519.VerifyPrehash(sig, sigOff, m_publicPoint, ctx, msg, msgOff);
default:
throw new ArgumentOutOfRangeException("algorithm");
}
}
public bool Verify(Ed25519.Algorithm algorithm, byte[] ctx, ReadOnlySpan<byte> msg, ReadOnlySpan<byte> sig)
{
switch (algorithm) {
case Ed25519.Algorithm.Ed25519:
if (ctx != null)
throw new ArgumentOutOfRangeException("ctx");
return Ed25519.Verify(sig, m_publicPoint, msg);
case Ed25519.Algorithm.Ed25519ctx:
if (ctx == null)
throw new ArgumentNullException("ctx");
if (ctx.Length > 255)
throw new ArgumentOutOfRangeException("ctx");
return Ed25519.Verify(sig, m_publicPoint, ctx, msg);
case Ed25519.Algorithm.Ed25519ph:
if (ctx == null)
throw new ArgumentNullException("ctx");
if (ctx.Length > 255)
throw new ArgumentOutOfRangeException("ctx");
return Ed25519.VerifyPrehash(sig, m_publicPoint, ctx, msg);
default:
throw new ArgumentOutOfRangeException("algorithm");
}
}
private static Ed25519.PublicPoint Parse(byte[] buf, int off)
{
Ed25519.PublicPoint publicPoint = Ed25519.ValidatePublicKeyPartialExport(buf, off);
if (publicPoint == null)
throw new ArgumentException("invalid public key");
return publicPoint;
}
private static Ed25519.PublicPoint Parse(ReadOnlySpan<byte> buf)
{
Ed25519.PublicPoint publicPoint = Ed25519.ValidatePublicKeyPartialExport(buf);
if (publicPoint == null)
throw new ArgumentException("invalid public key");
return publicPoint;
}
private static byte[] Validate(byte[] buf)
{
if (buf.Length != KeySize)
throw new ArgumentException("must have length " + KeySize.ToString(), "buf");
return buf;
}
}
}