1+ using Chaos . NaCl ;
2+ using Chaos . NaCl . Internal . Ed25519Ref10 ;
3+ using System ;
4+ #pragma warning disable CS1591 // Fehledes XML-Kommentar für öffentlich sichtbaren Typ oder Element
5+ namespace Renci . SshNet . Security . Cryptography . Ciphers
6+ {
7+ public class Ed25519
8+ {
9+ public static readonly int PublicKeySizeInBytes = 32 ;
10+ public static readonly int SignatureSizeInBytes = 64 ;
11+ public static readonly int ExpandedPrivateKeySizeInBytes = 32 * 2 ;
12+ public static readonly int PrivateKeySeedSizeInBytes = 32 ;
13+ public static readonly int SharedKeySizeInBytes = 32 ;
14+
15+ public static bool Verify ( ArraySegment < byte > signature , ArraySegment < byte > message , ArraySegment < byte > publicKey )
16+ {
17+ if ( signature . Count != SignatureSizeInBytes )
18+ throw new ArgumentException ( string . Format ( "Signature size must be {0}" , SignatureSizeInBytes ) , "signature.Count" ) ;
19+ if ( publicKey . Count != PublicKeySizeInBytes )
20+ throw new ArgumentException ( string . Format ( "Public key size must be {0}" , PublicKeySizeInBytes ) , "publicKey.Count" ) ;
21+ return Ed25519Operations . crypto_sign_verify ( signature . Array , signature . Offset , message . Array , message . Offset , message . Count , publicKey . Array , publicKey . Offset ) ;
22+ }
23+
24+ public static bool Verify ( byte [ ] signature , byte [ ] message , byte [ ] publicKey )
25+ {
26+ if ( signature == null )
27+ throw new ArgumentNullException ( "signature" ) ;
28+ if ( message == null )
29+ throw new ArgumentNullException ( "message" ) ;
30+ if ( publicKey == null )
31+ throw new ArgumentNullException ( "publicKey" ) ;
32+ if ( signature . Length != SignatureSizeInBytes )
33+ throw new ArgumentException ( string . Format ( "Signature size must be {0}" , SignatureSizeInBytes ) , "signature.Length" ) ;
34+ if ( publicKey . Length != PublicKeySizeInBytes )
35+ throw new ArgumentException ( string . Format ( "Public key size must be {0}" , PublicKeySizeInBytes ) , "publicKey.Length" ) ;
36+ return Ed25519Operations . crypto_sign_verify ( signature , 0 , message , 0 , message . Length , publicKey , 0 ) ;
37+ }
38+
39+ public static void Sign ( ArraySegment < byte > signature , ArraySegment < byte > message , ArraySegment < byte > expandedPrivateKey )
40+ {
41+ if ( signature . Array == null )
42+ throw new ArgumentNullException ( "signature.Array" ) ;
43+ if ( signature . Count != SignatureSizeInBytes )
44+ throw new ArgumentException ( "signature.Count" ) ;
45+ if ( expandedPrivateKey . Array == null )
46+ throw new ArgumentNullException ( "expandedPrivateKey.Array" ) ;
47+ if ( expandedPrivateKey . Count != ExpandedPrivateKeySizeInBytes )
48+ throw new ArgumentException ( "expandedPrivateKey.Count" ) ;
49+ if ( message . Array == null )
50+ throw new ArgumentNullException ( "message.Array" ) ;
51+ Ed25519Operations . crypto_sign2 ( signature . Array , signature . Offset , message . Array , message . Offset , message . Count , expandedPrivateKey . Array , expandedPrivateKey . Offset ) ;
52+ }
53+
54+ public static byte [ ] Sign ( byte [ ] message , byte [ ] expandedPrivateKey )
55+ {
56+ var signature = new byte [ SignatureSizeInBytes ] ;
57+ Sign ( new ArraySegment < byte > ( signature ) , new ArraySegment < byte > ( message ) , new ArraySegment < byte > ( expandedPrivateKey ) ) ;
58+ return signature ;
59+ }
60+
61+ public static byte [ ] PublicKeyFromSeed ( byte [ ] privateKeySeed )
62+ {
63+ byte [ ] privateKey ;
64+ byte [ ] publicKey ;
65+ KeyPairFromSeed ( out publicKey , out privateKey , privateKeySeed ) ;
66+ CryptoBytes . Wipe ( privateKey ) ;
67+ return publicKey ;
68+ }
69+
70+ public static byte [ ] ExpandedPrivateKeyFromSeed ( byte [ ] privateKeySeed )
71+ {
72+ byte [ ] privateKey ;
73+ byte [ ] publicKey ;
74+ KeyPairFromSeed ( out publicKey , out privateKey , privateKeySeed ) ;
75+ CryptoBytes . Wipe ( publicKey ) ;
76+ return privateKey ;
77+ }
78+
79+ public static void KeyPairFromSeed ( out byte [ ] publicKey , out byte [ ] expandedPrivateKey , byte [ ] privateKeySeed )
80+ {
81+ if ( privateKeySeed == null )
82+ throw new ArgumentNullException ( "privateKeySeed" ) ;
83+ if ( privateKeySeed . Length != PrivateKeySeedSizeInBytes )
84+ throw new ArgumentException ( "privateKeySeed" ) ;
85+ var pk = new byte [ PublicKeySizeInBytes ] ;
86+ var sk = new byte [ ExpandedPrivateKeySizeInBytes ] ;
87+ Ed25519Operations . crypto_sign_keypair ( pk , 0 , sk , 0 , privateKeySeed , 0 ) ;
88+ publicKey = pk ;
89+ expandedPrivateKey = sk ;
90+ }
91+
92+ public static void KeyPairFromSeed ( ArraySegment < byte > publicKey , ArraySegment < byte > expandedPrivateKey , ArraySegment < byte > privateKeySeed )
93+ {
94+ if ( publicKey . Array == null )
95+ throw new ArgumentNullException ( "publicKey.Array" ) ;
96+ if ( expandedPrivateKey . Array == null )
97+ throw new ArgumentNullException ( "expandedPrivateKey.Array" ) ;
98+ if ( privateKeySeed . Array == null )
99+ throw new ArgumentNullException ( "privateKeySeed.Array" ) ;
100+ if ( publicKey . Count != PublicKeySizeInBytes )
101+ throw new ArgumentException ( "publicKey.Count" ) ;
102+ if ( expandedPrivateKey . Count != ExpandedPrivateKeySizeInBytes )
103+ throw new ArgumentException ( "expandedPrivateKey.Count" ) ;
104+ if ( privateKeySeed . Count != PrivateKeySeedSizeInBytes )
105+ throw new ArgumentException ( "privateKeySeed.Count" ) ;
106+ Ed25519Operations . crypto_sign_keypair (
107+ publicKey . Array , publicKey . Offset ,
108+ expandedPrivateKey . Array , expandedPrivateKey . Offset ,
109+ privateKeySeed . Array , privateKeySeed . Offset ) ;
110+ }
111+
112+ [ Obsolete ( "Needs more testing" ) ]
113+ public static byte [ ] KeyExchange ( byte [ ] publicKey , byte [ ] privateKey )
114+ {
115+ var sharedKey = new byte [ SharedKeySizeInBytes ] ;
116+ KeyExchange ( new ArraySegment < byte > ( sharedKey ) , new ArraySegment < byte > ( publicKey ) , new ArraySegment < byte > ( privateKey ) ) ;
117+ return sharedKey ;
118+ }
119+
120+ [ Obsolete ( "Needs more testing" ) ]
121+ public static void KeyExchange ( ArraySegment < byte > sharedKey , ArraySegment < byte > publicKey , ArraySegment < byte > privateKey )
122+ {
123+ if ( sharedKey . Array == null )
124+ throw new ArgumentNullException ( "sharedKey.Array" ) ;
125+ if ( publicKey . Array == null )
126+ throw new ArgumentNullException ( "publicKey.Array" ) ;
127+ if ( privateKey . Array == null )
128+ throw new ArgumentNullException ( "privateKey" ) ;
129+ if ( sharedKey . Count != 32 )
130+ throw new ArgumentException ( "sharedKey.Count != 32" ) ;
131+ if ( publicKey . Count != 32 )
132+ throw new ArgumentException ( "publicKey.Count != 32" ) ;
133+ if ( privateKey . Count != 64 )
134+ throw new ArgumentException ( "privateKey.Count != 64" ) ;
135+
136+ FieldElement montgomeryX , edwardsY , edwardsZ , sharedMontgomeryX ;
137+ FieldOperations . fe_frombytes ( out edwardsY , publicKey . Array , publicKey . Offset ) ;
138+ FieldOperations . fe_1 ( out edwardsZ ) ;
139+ MontgomeryCurve25519 . EdwardsToMontgomeryX ( out montgomeryX , ref edwardsY , ref edwardsZ ) ;
140+ byte [ ] h = Sha512 . Hash ( privateKey . Array , privateKey . Offset , 32 ) ; //ToDo: Remove alloc
141+ ScalarOperations . sc_clamp ( h , 0 ) ;
142+ MontgomeryOperations . scalarmult ( out sharedMontgomeryX , h , 0 , ref montgomeryX ) ;
143+ CryptoBytes . Wipe ( h ) ;
144+ FieldOperations . fe_tobytes ( sharedKey . Array , sharedKey . Offset , ref sharedMontgomeryX ) ;
145+ MontgomeryCurve25519 . KeyExchangeOutputHashNaCl ( sharedKey . Array , sharedKey . Offset ) ;
146+ }
147+ }
148+ }
149+ #pragma warning restore CS1591 // Fehledes XML-Kommentar für öffentlich sichtbaren Typ oder Element
0 commit comments