123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- using System;
- using Org.BouncyCastle.Crypto.Parameters;
- using Org.BouncyCastle.Math;
- using Org.BouncyCastle.Security;
- namespace Org.BouncyCastle.Crypto.Engines
- {
-
- public class ElGamalEngine
- : IAsymmetricBlockCipher
- {
- private ElGamalKeyParameters key;
- private SecureRandom random;
- private bool forEncryption;
- private int bitSize;
- public virtual string AlgorithmName
- {
- get { return "ElGamal"; }
- }
-
- public virtual void Init(
- bool forEncryption,
- ICipherParameters parameters)
- {
- if (parameters is ParametersWithRandom)
- {
- ParametersWithRandom p = (ParametersWithRandom) parameters;
- this.key = (ElGamalKeyParameters) p.Parameters;
- this.random = p.Random;
- }
- else
- {
- this.key = (ElGamalKeyParameters) parameters;
- this.random = new SecureRandom();
- }
- this.forEncryption = forEncryption;
- this.bitSize = key.Parameters.P.BitLength;
- if (forEncryption)
- {
- if (!(key is ElGamalPublicKeyParameters))
- {
- throw new ArgumentException("ElGamalPublicKeyParameters are required for encryption.");
- }
- }
- else
- {
- if (!(key is ElGamalPrivateKeyParameters))
- {
- throw new ArgumentException("ElGamalPrivateKeyParameters are required for decryption.");
- }
- }
- }
-
- public virtual int GetInputBlockSize()
- {
- if (forEncryption)
- {
- return (bitSize - 1) / 8;
- }
- return 2 * ((bitSize + 7) / 8);
- }
-
- public virtual int GetOutputBlockSize()
- {
- if (forEncryption)
- {
- return 2 * ((bitSize + 7) / 8);
- }
- return (bitSize - 1) / 8;
- }
-
- public virtual byte[] ProcessBlock(
- byte[] input,
- int inOff,
- int length)
- {
- if (key == null)
- throw new InvalidOperationException("ElGamal engine not initialised");
- int maxLength = forEncryption
- ? (bitSize - 1 + 7) / 8
- : GetInputBlockSize();
- if (length > maxLength)
- throw new DataLengthException("input too large for ElGamal cipher.\n");
- BigInteger p = key.Parameters.P;
- byte[] output;
- if (key is ElGamalPrivateKeyParameters)
- {
- int halfLength = length / 2;
- BigInteger gamma = new BigInteger(1, input, inOff, halfLength);
- BigInteger phi = new BigInteger(1, input, inOff + halfLength, halfLength);
- ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters) key;
-
-
- BigInteger m = gamma.ModPow(p.Subtract(BigInteger.One).Subtract(priv.X), p).Multiply(phi).Mod(p);
- output = m.ToByteArrayUnsigned();
- }
- else
- {
- BigInteger tmp = new BigInteger(1, input, inOff, length);
- if (tmp.BitLength >= p.BitLength)
- throw new DataLengthException("input too large for ElGamal cipher.\n");
- ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters) key;
- BigInteger pSub2 = p.Subtract(BigInteger.Two);
-
- BigInteger k;
- do
- {
- k = new BigInteger(p.BitLength, random);
- }
- while (k.SignValue == 0 || k.CompareTo(pSub2) > 0);
- BigInteger g = key.Parameters.G;
- BigInteger gamma = g.ModPow(k, p);
- BigInteger phi = tmp.Multiply(pub.Y.ModPow(k, p)).Mod(p);
- output = new byte[this.GetOutputBlockSize()];
-
- byte[] out1 = gamma.ToByteArrayUnsigned();
- byte[] out2 = phi.ToByteArrayUnsigned();
- out1.CopyTo(output, output.Length / 2 - out1.Length);
- out2.CopyTo(output, output.Length - out2.Length);
- }
- return output;
- }
- }
- }
- #endif
|