# < Summary

Information

Class: | Renci.SshNet.Security.Chaos.NaCl.MontgomeryCurve25519
Assembly: | Renci.SshNet
File(s): | \home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\Chaos.NaCl\MontgomeryCurve25519.cs

Line coverage
11%

Covered lines: | 11
Uncovered lines: | 84
Coverable lines: | 95
Total lines: | 142
Line coverage: | 11.5%

Branch coverage
0%

Covered branches: | 0
Total branches: | 26
Branch coverage: | 0%

Method coverage

Feature is only available for sponsors

Upgrade to PRO version

# Metrics

Method | Branch coverage | Cyclomatic complexity | Line coverage
--- | --- | --- | ---
.cctor() | 100% | 1 | 100%
GetPublicKey(...) | 0% | 4 | 0%
GetPublicKey(...) | 0% | 10 | 0%
KeyExchangeOutputHashCurve25519Paper(...) | 100% | 1 | 0%
KeyExchangeOutputHashNaCl(...) | 100% | 1 | 0%
KeyExchange(...) | 100% | 1 | 0%
KeyExchange(...) | 0% | 12 | 0%
EdwardsToMontgomeryX(...) | 100% | 1 | 0%

# File(s)

## \home\appveyor\projects\ssh-net\src\Renci.SshNet\Security\Chaos.NaCl\MontgomeryCurve25519.cs

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | `using System.Collections.Generic;`
|  | `3` |  | `using Renci.SshNet.Security.Chaos.NaCl.Internal;`
|  | `4` |  | `using Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10;`
|  | `5` |  | `using Renci.SshNet.Security.Chaos.NaCl.Internal.Salsa;`
|  | `6` |  | ``
|  | `7` |  | `namespace Renci.SshNet.Security.Chaos.NaCl`
|  | `8` |  | `{`
|  | `9` |  | `// This class is mainly for compatibility with NaCl's Curve25519 implementation`
|  | `10` |  | `// If you don't need that compatibility, use Ed25519.KeyExchange`
|  | `11` |  | `internal static class MontgomeryCurve25519`
|  | `12` |  | `{`
| 1 | `13` |  | `internal static readonly int PublicKeySizeInBytes = 32;`
| 1 | `14` |  | `internal static readonly int PrivateKeySizeInBytes = 32;`
| 1 | `15` |  | `internal static readonly int SharedKeySizeInBytes = 32;`
|  | `16` |  | ``
|  | `17` |  | `internal static byte[] GetPublicKey(byte[] privateKey)`
| 0 | `18` |  | `{`
| 0 | `19` |  | `if (privateKey == null)`
| 0 | `20` |  | `throw new ArgumentNullException("privateKey");`
| 0 | `21` |  | `if (privateKey.Length != PrivateKeySizeInBytes)`
| 0 | `22` |  | `throw new ArgumentException("privateKey.Length must be 32");`
| 0 | `23` |  | `var publicKey = new byte[32];`
| 0 | `24` |  | `GetPublicKey(new ArraySegment<byte>(publicKey), new ArraySegment<byte>(privateKey));`
| 0 | `25` |  | `return publicKey;`
| 0 | `26` |  | `}`
|  | `27` |  | ``
| 1 | `28` |  | `static readonly byte[] _basePoint = new byte[32]`
| 1 | `29` |  | `{`
| 1 | `30` |  | `9, 0, 0, 0, 0, 0, 0, 0,`
| 1 | `31` |  | `0, 0, 0 ,0, 0, 0, 0, 0,`
| 1 | `32` |  | `0, 0, 0 ,0, 0, 0, 0, 0,`
| 1 | `33` |  | `0, 0, 0 ,0, 0, 0, 0, 0`
| 1 | `34` |  | `};`
|  | `35` |  | ``
|  | `36` |  | `internal static void GetPublicKey(ArraySegment<byte> publicKey, ArraySegment<byte> privateKey)`
| 0 | `37` |  | `{`
| 0 | `38` |  | `if (publicKey.Array == null)`
| 0 | `39` |  | `throw new ArgumentNullException("publicKey.Array");`
| 0 | `40` |  | `if (privateKey.Array == null)`
| 0 | `41` |  | `throw new ArgumentNullException("privateKey.Array");`
| 0 | `42` |  | `if (publicKey.Count != PublicKeySizeInBytes)`
| 0 | `43` |  | `throw new ArgumentException("privateKey.Count must be 32");`
| 0 | `44` |  | `if (privateKey.Count != PrivateKeySizeInBytes)`
| 0 | `45` |  | `throw new ArgumentException("privateKey.Count must be 32");`
|  | `46` |  | ``
|  | `47` |  | `// hack: abusing publicKey as temporary storage`
|  | `48` |  | `// todo: remove hack`
| 0 | `49` |  | `for (int i = 0; i < 32; i++)`
| 0 | `50` |  | `{`
| 0 | `51` |  | `publicKey.Array[publicKey.Offset + i] = privateKey.Array[privateKey.Offset + i];`
| 0 | `52` |  | `}`
| 0 | `53` |  | `ScalarOperations.sc_clamp(publicKey.Array, publicKey.Offset);`
|  | `54` |  | ``
|  | `55` |  | `GroupElementP3 A;`
| 0 | `56` |  | `GroupOperations.ge_scalarmult_base(out A, publicKey.Array, publicKey.Offset);`
|  | `57` |  | `FieldElement publicKeyFE;`
| 0 | `58` |  | `EdwardsToMontgomeryX(out publicKeyFE, ref A.Y, ref A.Z);`
| 0 | `59` |  | `FieldOperations.fe_tobytes(publicKey.Array, publicKey.Offset, ref publicKeyFE);`
| 0 | `60` |  | `}`
|  | `61` |  | ``
|  | `62` |  | `// hashes like the Curve25519 paper says`
|  | `63` |  | `internal static void KeyExchangeOutputHashCurve25519Paper(byte[] sharedKey, int offset)`
| 0 | `64` |  | `{`
|  | `65` |  | `//c = Curve25519output`
|  | `66` |  | `const UInt32 c0 = 'C' | 'u' << 8 | 'r' << 16 | (UInt32)'v' << 24;`
|  | `67` |  | `const UInt32 c1 = 'e' | '2' << 8 | '5' << 16 | (UInt32)'5' << 24;`
|  | `68` |  | `const UInt32 c2 = '1' | '9' << 8 | 'o' << 16 | (UInt32)'u' << 24;`
|  | `69` |  | `const UInt32 c3 = 't' | 'p' << 8 | 'u' << 16 | (UInt32)'t' << 24;`
|  | `70` |  | ``
|  | `71` |  | `Array16<UInt32> salsaState;`
| 0 | `72` |  | `salsaState.x0 = c0;`
| 0 | `73` |  | `salsaState.x1 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 0);`
| 0 | `74` |  | `salsaState.x2 = 0;`
| 0 | `75` |  | `salsaState.x3 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 4);`
| 0 | `76` |  | `salsaState.x4 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 8);`
| 0 | `77` |  | `salsaState.x5 = c1;`
| 0 | `78` |  | `salsaState.x6 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 12);`
| 0 | `79` |  | `salsaState.x7 = 0;`
| 0 | `80` |  | `salsaState.x8 = 0;`
| 0 | `81` |  | `salsaState.x9 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 16);`
| 0 | `82` |  | `salsaState.x10 = c2;`
| 0 | `83` |  | `salsaState.x11 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 20);`
| 0 | `84` |  | `salsaState.x12 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 24);`
| 0 | `85` |  | `salsaState.x13 = 0;`
| 0 | `86` |  | `salsaState.x14 = ByteIntegerConverter.LoadLittleEndian32(sharedKey, offset + 28);`
| 0 | `87` |  | `salsaState.x15 = c3;`
| 0 | `88` |  | `SalsaCore.Salsa(out salsaState, ref salsaState, 20);`
|  | `89` |  | ``
| 0 | `90` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 0, salsaState.x0);`
| 0 | `91` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 4, salsaState.x1);`
| 0 | `92` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 8, salsaState.x2);`
| 0 | `93` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 12, salsaState.x3);`
| 0 | `94` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 16, salsaState.x4);`
| 0 | `95` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 20, salsaState.x5);`
| 0 | `96` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 24, salsaState.x6);`
| 0 | `97` |  | `ByteIntegerConverter.StoreLittleEndian32(sharedKey, offset + 28, salsaState.x7);`
| 0 | `98` |  | `}`
|  | `99` |  | ``
| 1 | `100` |  | `private static readonly byte[] _zero16 = new byte[16];`
|  | `101` |  | ``
|  | `102` |  | `// hashes like the NaCl paper says instead i.e. HSalsa(x,0)`
|  | `103` |  | `internal static void KeyExchangeOutputHashNaCl(byte[] sharedKey, int offset)`
| 0 | `104` |  | `{`
| 0 | `105` |  | `Salsa20.HSalsa20(sharedKey, offset, sharedKey, offset, _zero16, 0);`
| 0 | `106` |  | `}`
|  | `107` |  | ``
|  | `108` |  | `internal static byte[] KeyExchange(byte[] publicKey, byte[] privateKey)`
| 0 | `109` |  | `{`
| 0 | `110` |  | `var sharedKey = new byte[SharedKeySizeInBytes];`
| 0 | `111` |  | `KeyExchange(new ArraySegment<byte>(sharedKey), new ArraySegment<byte>(publicKey), new ArraySegment<byte>(pri`
| 0 | `112` |  | `return sharedKey;`
| 0 | `113` |  | `}`
|  | `114` |  | ``
|  | `115` |  | `internal static void KeyExchange(ArraySegment<byte> sharedKey, ArraySegment<byte> publicKey, ArraySegment<byte>`
| 0 | `116` |  | `{`
| 0 | `117` |  | `if (sharedKey.Array == null)`
| 0 | `118` |  | `throw new ArgumentNullException("sharedKey.Array");`
| 0 | `119` |  | `if (publicKey.Array == null)`
| 0 | `120` |  | `throw new ArgumentNullException("publicKey.Array");`
| 0 | `121` |  | `if (privateKey.Array == null)`
| 0 | `122` |  | `throw new ArgumentNullException("privateKey");`
| 0 | `123` |  | `if (sharedKey.Count != 32)`
| 0 | `124` |  | `throw new ArgumentException("sharedKey.Count != 32");`
| 0 | `125` |  | `if (publicKey.Count != 32)`
| 0 | `126` |  | `throw new ArgumentException("publicKey.Count != 32");`
| 0 | `127` |  | `if (privateKey.Count != 32)`
| 0 | `128` |  | `throw new ArgumentException("privateKey.Count != 32");`
| 0 | `129` |  | `MontgomeryOperations.scalarmult(sharedKey.Array, sharedKey.Offset, privateKey.Array, privateKey.Offset, publ`
| 0 | `130` |  | `KeyExchangeOutputHashNaCl(sharedKey.Array, sharedKey.Offset);`
| 0 | `131` |  | `}`
|  | `132` |  | ``
|  | `133` |  | `internal static void EdwardsToMontgomeryX(out FieldElement montgomeryX, ref FieldElement edwardsY, ref FieldElem`
| 0 | `134` |  | `{`
|  | `135` |  | `FieldElement tempX, tempZ;`
| 0 | `136` |  | `FieldOperations.fe_add(out tempX, ref edwardsZ, ref edwardsY);`
| 0 | `137` |  | `FieldOperations.fe_sub(out tempZ, ref edwardsZ, ref edwardsY);`
| 0 | `138` |  | `FieldOperations.fe_invert(out tempZ, ref tempZ);`
| 0 | `139` |  | `FieldOperations.fe_mul(out montgomeryX, ref tempX, ref tempZ);`
| 0 | `140` |  | `}`
|  | `141` |  | `}`
|  | `142` |  | `}`

# Methods/Properties

.cctor()
GetPublicKey(System.Byte[])
GetPublicKey(System.ArraySegment`1<System.Byte>,System.ArraySegment`1<System.Byte>)
KeyExchangeOutputHashCurve25519Paper(System.Byte[],System.Int32)
KeyExchangeOutputHashNaCl(System.Byte[],System.Int32)
KeyExchange(System.Byte[],System.Byte[])
KeyExchange(System.ArraySegment`1<System.Byte>,System.ArraySegment`1<System.Byte>,System.ArraySegment`1<System.Byte>)
EdwardsToMontgomeryX(Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10.FieldElement&,Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10.FieldElement&,Renci.SshNet.Security.Chaos.NaCl.Internal.Ed25519Ref10.FieldElement&)