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