summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-07-12 22:44:08 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-07-12 22:44:08 +0700
commitc7464b392dffc54616d4b7c149f6d9e0c6d790ee (patch)
treecd8eacfddfe9bb3ae6e5d6f7bd57ac62f2083e86
parentRemove redundant utility methods and refactor (diff)
downloadBouncyCastle.NET-ed25519-c7464b392dffc54616d4b7c149f6d9e0c6d790ee.tar.xz
Refactoring in Picnic
-rw-r--r--crypto/src/pqc/crypto/picnic/PicnicEngine.cs460
-rw-r--r--crypto/src/pqc/crypto/picnic/Utils.cs42
2 files changed, 217 insertions, 285 deletions
diff --git a/crypto/src/pqc/crypto/picnic/PicnicEngine.cs b/crypto/src/pqc/crypto/picnic/PicnicEngine.cs
index da6a9215c..605a27764 100644
--- a/crypto/src/pqc/crypto/picnic/PicnicEngine.cs
+++ b/crypto/src/pqc/crypto/picnic/PicnicEngine.cs
@@ -1,4 +1,5 @@
 using System;
+
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Digests;
 using Org.BouncyCastle.Crypto.Utilities;
@@ -270,46 +271,37 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             seedSizeBytes = Utils.NumBytes(2 * pqSecurityLevel);
             stateSizeWords = (stateSizeBits + WORD_SIZE_BITS - 1) / WORD_SIZE_BITS;
 
-
-
             switch (parameters)
             {
-                case 1:
-                case 3:
-                case 5:
-                case 7:
-                case 8:
-                case 9:
-                case 10:
-                case 11:
-                case 12:
-                    transform = TRANSFORM_FS;
-                    break;
-                case 2:
-                case 4:
-                case 6:
-                    transform = TRANSFORM_UR;
-                    break;
-                default:
-                    transform = TRANSFORM_INVALID;
-                    break;
+            case 1:
+            case 3:
+            case 5:
+            case 7:
+            case 8:
+            case 9:
+            case 10:
+            case 11:
+            case 12:
+                transform = TRANSFORM_FS;
+                break;
+            case 2:
+            case 4:
+            case 6:
+                transform = TRANSFORM_UR;
+                break;
+            default:
+                transform = TRANSFORM_INVALID;
+                break;
             }
 
-
             if (transform == 1)
             {
                 UnruhGWithoutInputBytes = seedSizeBytes + andSizeBytes;
                 UnruhGWithInputBytes = UnruhGWithoutInputBytes + stateSizeBytes;
             }
 
-            if (stateSizeBits == 128 || stateSizeBits == 129)
-            {
-                digest = new ShakeDigest(128);
-            }
-            else
-            {
-                digest = new ShakeDigest(256);
-            }
+            int shakeSize = (stateSizeBits == 128 || stateSizeBits == 129) ? 128 : 256;
+            digest = new ShakeDigest(shakeSize);
         }
 
         public bool crypto_sign_open(byte[] m, byte[] sm, byte[] pk)
@@ -317,7 +309,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             uint sigLen = Pack.LE_To_UInt32(sm, 0);
             byte[] m_from_sm = Arrays.CopyOfRange(sm, 4, 4 + m.Length);
             int ret = picnic_verify(pk, m_from_sm, sm, sigLen);
-            System.Array.Copy(sm, 4, m, 0, m.Length);
+            Array.Copy(sm, 4, m, 0, m.Length);
             return ret != -1;
         }
 
@@ -337,7 +329,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 Signature2 sig = new Signature2(this);
                 DeserializeSignature2(sig, signature, sigLen, message.Length + 4);
 
-
                 return verify_picnic3(sig, ciphertext, plaintext, message);
             }
             else
@@ -410,24 +401,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 // create ordered array of commitments with order computed based on the challenge
                 // check commitments of the two opened views
                 int challenge = GetChallenge(received_challengebits, i);
-                Commit(proofs[i].seed1, 0, view1s[i],  AS[i]
-                [challenge])
-
-                ;
-                Commit(proofs[i].seed2, 0, view2s[i],  AS[i]
-                [ (challenge
-
-                +1) % 3]);
-                System.Array.Copy(proofs[i].view3Commitment, 0,  AS[i]
-                [ (challenge
-
-                +2) % 3], 0, digestSizeBytes);
+                Commit(proofs[i].seed1, 0, view1s[i],  AS[i][challenge]);
+                Commit(proofs[i].seed2, 0, view2s[i],  AS[i][(challenge + 1) % 3]);
+                Array.Copy(proofs[i].view3Commitment, 0,  AS[i][(challenge + 2) % 3], 0, digestSizeBytes);
                 if (transform == TRANSFORM_UR)
                 {
                     G(challenge, proofs[i].seed1, 0, view1s[i], gs[i][challenge]);
                     G((challenge + 1) % 3, proofs[i].seed2, 0, view2s[i], gs[i][(challenge + 1) % 3]);
                     int view3UnruhLength = (challenge == 0) ? UnruhGWithInputBytes : UnruhGWithoutInputBytes;
-                    System.Array.Copy(proofs[i].view3UnruhG, 0, gs[i][(challenge + 2) % 3], 0, view3UnruhLength);
+                    Array.Copy(proofs[i].view3UnruhG, 0, gs[i][(challenge + 2) % 3], 0, view3UnruhLength);
                 }
 
                 viewOutputs[i][challenge] = view1s[i].outputShare;
@@ -439,9 +421,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
             computed_challengebits = new byte[Utils.NumBytes(2 * numMPCRounds)];
 
-            H3(pubKey, plaintext, viewOutputs, 
-                AS, computed_challengebits, sig.salt,
-            message, gs);
+            H3(pubKey, plaintext, viewOutputs, AS, computed_challengebits, sig.salt, message, gs);
 
             if (!SubarrayEquals(received_challengebits, computed_challengebits, Utils.NumBytes(2 * numMPCRounds)))
             {
@@ -455,7 +435,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
         void VerifyProof(Signature.Proof proof, View view1, View view2, int challenge, byte[] salt, 
             uint roundNumber, byte[] tmp, uint[] plaintext, Tape tape)
         {
-            System.Array.Copy(proof.communicatedBits, 0, view2.communicatedBits, 0, andSizeBytes);
+            Array.Copy(proof.communicatedBits, 0, view2.communicatedBits, 0, andSizeBytes);
             tape.pos = 0;
 
 //        Console.Error.Write("tmp: " + Hex.toHexString(tmp));
@@ -463,66 +443,71 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             bool status = false;
             switch (challenge)
             {
-                case 0:
-                    // in this case, both views' inputs are derivable from the input share
-                    status = CreateRandomTape(proof.seed1, 0, salt, roundNumber,
-                        0, tmp, stateSizeBytes + andSizeBytes);
+            case 0:
+            {
+                // in this case, both views' inputs are derivable from the input share
+                status = CreateRandomTape(proof.seed1, 0, salt, roundNumber,
+                    0, tmp, stateSizeBytes + andSizeBytes);
 
-                    Pack.LE_To_UInt32(tmp, 0, view1.inputShare); //todo check
-                    System.Array.Copy(tmp, stateSizeBytes, tape.tapes[0], 0, andSizeBytes);
+                Pack.LE_To_UInt32(tmp, 0, view1.inputShare); //todo check
+                Array.Copy(tmp, stateSizeBytes, tape.tapes[0], 0, andSizeBytes);
 
-                    status = status && CreateRandomTape(proof.seed2, 0, salt, roundNumber,
-                        1, tmp, stateSizeBytes + andSizeBytes);
-
-                    if (!status)
-                    {
-                        break;
-                    }
-
-                    Pack.LE_To_UInt32(tmp, 0, view2.inputShare); //todo check
-                    System.Array.Copy(tmp, stateSizeBytes, tape.tapes[1], 0, andSizeBytes);
+                status = status && CreateRandomTape(proof.seed2, 0, salt, roundNumber,
+                    1, tmp, stateSizeBytes + andSizeBytes);
 
+                if (!status)
+                {
                     break;
+                }
 
-                case 1:
-                    // in this case view2's input share was already given to us explicitly as
-                    // it is not computable from the seed. We just need to compute view1's input from
-                    // its seed
-                    status = CreateRandomTape(proof.seed1, 0, salt, roundNumber,
-                        1, tmp, stateSizeBytes + andSizeBytes);
-
-                    Pack.LE_To_UInt32(tmp, 0, view1.inputShare); //todo check
-                    System.Array.Copy(tmp, stateSizeBytes, tape.tapes[0], 0, andSizeBytes);
-                    status = status && CreateRandomTape(proof.seed2, 0, salt, roundNumber,
-                        2, tape.tapes[1], andSizeBytes);
-                    if (!status)
-                    {
-                        break;
-                    }
-
-                    System.Array.Copy(proof.inputShare, 0, view2.inputShare, 0, stateSizeBytes);
-                    break;
+                Pack.LE_To_UInt32(tmp, 0, view2.inputShare); //todo check
+                Array.Copy(tmp, stateSizeBytes, tape.tapes[1], 0, andSizeBytes);
 
-                case 2:
-                    // in this case view1's input share was already given to us explicitly as
-                    // it is not computable from the seed. We just need to compute view2's input from
-                    // its seed
-                    status = CreateRandomTape(proof.seed1, 0, salt, roundNumber, 2, tape.tapes[0], andSizeBytes);
-                    System.Array.Copy(proof.inputShare, 0, view1.inputShare, 0, stateSizeBytes);
-                    status = status && CreateRandomTape(proof.seed2, 0, salt, roundNumber, 0, tmp,
-                        (stateSizeBytes + andSizeBytes));
-                    if (!status)
-                    {
-                        break;
-                    }
+                break;
+            }
+            case 1:
+            {
+                // in this case view2's input share was already given to us explicitly as
+                // it is not computable from the seed. We just need to compute view1's input from
+                // its seed
+                status = CreateRandomTape(proof.seed1, 0, salt, roundNumber,
+                    1, tmp, stateSizeBytes + andSizeBytes);
 
-                    Pack.LE_To_UInt32(tmp, 0, view2.inputShare); //todo check
-                    System.Array.Copy(tmp, stateSizeBytes, tape.tapes[1], 0, andSizeBytes);
+                Pack.LE_To_UInt32(tmp, 0, view1.inputShare); //todo check
+                Array.Copy(tmp, stateSizeBytes, tape.tapes[0], 0, andSizeBytes);
+                status = status && CreateRandomTape(proof.seed2, 0, salt, roundNumber,
+                    2, tape.tapes[1], andSizeBytes);
+                if (!status)
+                {
                     break;
+                }
 
-                default:
-                    Console.Error.Write("Invalid Challenge!");
+                Array.Copy(proof.inputShare, 0, view2.inputShare, 0, stateSizeBytes);
+                break;
+            }
+            case 2:
+            {
+                // in this case view1's input share was already given to us explicitly as
+                // it is not computable from the seed. We just need to compute view2's input from
+                // its seed
+                status = CreateRandomTape(proof.seed1, 0, salt, roundNumber, 2, tape.tapes[0], andSizeBytes);
+                Array.Copy(proof.inputShare, 0, view1.inputShare, 0, stateSizeBytes);
+                status = status && CreateRandomTape(proof.seed2, 0, salt, roundNumber, 0, tmp,
+                    (stateSizeBytes + andSizeBytes));
+                if (!status)
+                {
                     break;
+                }
+
+                Pack.LE_To_UInt32(tmp, 0, view2.inputShare); //todo check
+                Array.Copy(tmp, stateSizeBytes, tape.tapes[1], 0, andSizeBytes);
+                break;
+            }
+            default:
+            {
+                Console.Error.Write("Invalid Challenge!");
+                break;
+            }
             }
 
             if (!status)
@@ -536,12 +521,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             Pack.UInt32_To_LE(view1.inputShare, view_bytes, 0);
             Arrays.Fill(view_bytes, stateSizeBytes, view_bytes.Length,
                 (byte) 0); //todo have correct size: reduce view.inputshare by /4
-            ZeroTrailingBits(view_bytes, stateSizeBits);
+            Utils.ZeroTrailingBits(view_bytes, stateSizeBits);
             Pack.LE_To_UInt32(view_bytes, 0, view1.inputShare);
 
             Pack.UInt32_To_LE(view2.inputShare, view_bytes, 0);
             Arrays.Fill(view_bytes, stateSizeBytes, view_bytes.Length, (byte) 0);
-            ZeroTrailingBits(view_bytes, stateSizeBits);
+            Utils.ZeroTrailingBits(view_bytes, stateSizeBits);
 
             Pack.LE_To_UInt32(view_bytes, 0, view2.inputShare);
 
@@ -551,7 +536,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
         void mpc_LowMC_verify(View view1, View view2, Tape tapes, uint[] tmp, uint[] plaintext,  int challenge)
         {
-
             Utils.Fill(tmp, 0, tmp.Length, 0);
 
             mpc_xor_constant_verify(tmp, plaintext, 0, stateSizeWords, challenge);
@@ -588,13 +572,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 mpc_xor(tmp, tmp, stateSizeWords, 2);
             }
 
-            System.Array.Copy(tmp, 2 * stateSizeWords, view1.outputShare, 0, stateSizeWords);
-            System.Array.Copy(tmp, 3 * stateSizeWords, view2.outputShare, 0, stateSizeWords);
+            Array.Copy(tmp, 2 * stateSizeWords, view1.outputShare, 0, stateSizeWords);
+            Array.Copy(tmp, 3 * stateSizeWords, view2.outputShare, 0, stateSizeWords);
         }
 
         void mpc_substitution_verify(uint[] state, Tape rand, View view1, View view2)
         {
-
             uint[] a = new uint[2];
             uint[] b = new uint[2];
             uint[] c = new uint[2];
@@ -606,7 +589,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             int stateOffset;
             for (int i = 0; i < numSboxes * 3; i += 3)
             {
-
                 for (int j = 0; j < 2; j++)
                 {
                     stateOffset = ((2 + j) * stateSizeWords) * 32;
@@ -691,7 +673,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 return -1;
             }
 
-            System.Array.Copy(sigBytes, sigBytesOffset, challengeBits, 0, Utils.NumBytes(2 * numMPCRounds));
+            Array.Copy(sigBytes, sigBytesOffset, challengeBits, 0, Utils.NumBytes(2 * numMPCRounds));
             sigBytesOffset += Utils.NumBytes(2 * numMPCRounds);
 
             if (!IsChallengeValid(challengeBits))
@@ -699,32 +681,31 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 return -1;
             }
 
-            System.Array.Copy(sigBytes, sigBytesOffset, sig.salt, 0, saltSizeBytes);
+            Array.Copy(sigBytes, sigBytesOffset, sig.salt, 0, saltSizeBytes);
             sigBytesOffset += saltSizeBytes;
 
             for (int i = 0; i < numMPCRounds; i++)
             {
-
                 int challenge = GetChallenge(challengeBits, i);
 
-                System.Array.Copy(sigBytes, sigBytesOffset, proofs[i].view3Commitment, 0, digestSizeBytes);
+                Array.Copy(sigBytes, sigBytesOffset, proofs[i].view3Commitment, 0, digestSizeBytes);
 
                 sigBytesOffset += digestSizeBytes;
 
                 if (transform == TRANSFORM_UR)
                 {
                     int view3UnruhLength = (challenge == 0) ? UnruhGWithInputBytes : UnruhGWithoutInputBytes;
-                    System.Array.Copy(sigBytes, sigBytesOffset, proofs[i].view3UnruhG, 0, view3UnruhLength);
+                    Array.Copy(sigBytes, sigBytesOffset, proofs[i].view3UnruhG, 0, view3UnruhLength);
                     sigBytesOffset += view3UnruhLength;
                 }
 
-                System.Array.Copy(sigBytes, sigBytesOffset, proofs[i].communicatedBits, 0, andSizeBytes);
+                Array.Copy(sigBytes, sigBytesOffset, proofs[i].communicatedBits, 0, andSizeBytes);
                 sigBytesOffset += andSizeBytes;
 
-                System.Array.Copy(sigBytes, sigBytesOffset, proofs[i].seed1, 0, seedSizeBytes);
+                Array.Copy(sigBytes, sigBytesOffset, proofs[i].seed1, 0, seedSizeBytes);
                 sigBytesOffset += seedSizeBytes;
 
-                System.Array.Copy(sigBytes, sigBytesOffset, proofs[i].seed2, 0, seedSizeBytes);
+                Array.Copy(sigBytes, sigBytesOffset, proofs[i].seed2, 0, seedSizeBytes);
                 sigBytesOffset += seedSizeBytes;
 
                 if (challenge == 1 || challenge == 2)
@@ -783,8 +764,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
         private  uint picnic_read_public_key(byte[] ciphertext, byte[] plaintext, byte[] pk)
         {
-            System.Array.Copy(pk, 1, ciphertext, 0, stateSizeBytes);
-            System.Array.Copy(pk, 1 + stateSizeBytes, plaintext, 0, stateSizeBytes);
+            Array.Copy(pk, 1, ciphertext, 0, stateSizeBytes);
+            Array.Copy(pk, 1 + stateSizeBytes, plaintext, 0, stateSizeBytes);
             return 0;
         }
 
@@ -866,8 +847,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                  * random tape. */
                 CreateRandomTapes(tapes[t], seeds[t].GetLeaves(), seeds[t].GetLeavesOffset(), sig.salt, t);
 
-
-
                 if (!Contains(sig.challengeC, numOpenedRounds, t))
                 {
                     /* We're given iSeed, have expanded the seeds, compute aux from scratch so we can comnpte Com[t] */
@@ -884,8 +863,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 {
                     /* We're given all seeds and aux bits, except for the unopened
                      * party, we get their commitment */
-                     uint unopened = sig.challengeP[IndexOf(sig.challengeC, numOpenedRounds, t)];
-
+                    uint unopened = sig.challengeP[IndexOf(sig.challengeC, numOpenedRounds, t)];
 
                     for (uint j = 0; j < last; j++)
                     {
@@ -900,9 +878,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                         commit(C[t][last], seeds[t].GetLeaf(last), sig.proofs[t].aux, sig.salt, t, last);
                     }
 
-                    System.Array.Copy(sig.proofs[t].C, 0, C[t][unopened], 0, digestSizeBytes);
+                    Array.Copy(sig.proofs[t].C, 0, C[t][unopened], 0, digestSizeBytes);
                 }
-
             }
 
             /* Commit to the commitments */
@@ -919,7 +896,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 if (Contains(sig.challengeC, numOpenedRounds, (uint)t))
                 {
                     /* 2. When t is in C, we have everything we need to re-compute the view, as an honest signer would.
-                     * We simulate the MPC with one fewer party; the unopned party's values are all set to zero. */
+                     * We simulate the MPC with one fewer party; the unopened party's values are all set to zero. */
                     uint unopened = sig.challengeP[IndexOf(sig.challengeC, numOpenedRounds, t)];
 
                     int tapeLengthBytes = 2 * andSizeBytes;
@@ -929,13 +906,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                         tapes[t].SetAuxBits(sig.proofs[t].aux);
                     }
                     
-                    System.Array.Copy(sig.proofs[t].msgs, 0, msgs[t].msgs[unopened], 0, andSizeBytes);
+                    Array.Copy(sig.proofs[t].msgs, 0, msgs[t].msgs[unopened], 0, andSizeBytes);
 
                     Arrays.Fill(tapes[t].tapes[unopened], (byte) 0);
                     msgs[t].unopened =  (int) unopened;
 
                     byte[] input_bytes = new byte[stateSizeWords * 4];
-                    System.Array.Copy(sig.proofs[t].input, 0, input_bytes, 0, sig.proofs[t].input.Length);
+                    Array.Copy(sig.proofs[t].input, 0, input_bytes, 0, sig.proofs[t].input.Length);
 
                     uint[] temp = new uint[stateSizeWords];
                     Pack.LE_To_UInt32(input_bytes, 0, temp, 0, stateSizeWords);
@@ -992,10 +969,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 return -1;
             }
 
-            System.Array.Copy(sigBytes, sigBytesOffset, sig.challengeHash, 0, digestSizeBytes);
+            Array.Copy(sigBytes, sigBytesOffset, sig.challengeHash, 0, digestSizeBytes);
             sigBytesOffset += digestSizeBytes;
 
-            System.Array.Copy(sigBytes, sigBytesOffset, sig.salt, 0, saltSizeBytes);
+            Array.Copy(sigBytes, sigBytesOffset, sig.salt, 0, saltSizeBytes);
             sigBytesOffset += saltSizeBytes;
 
             ExpandChallengeHash(sig.challengeHash, sig.challengeC, sig.challengeP);
@@ -1042,12 +1019,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             }
 
             sig.iSeedInfo = new byte[sig.iSeedInfoLen];
-            System.Array.Copy(sigBytes, sigBytesOffset, sig.iSeedInfo, 0, sig.iSeedInfoLen);
+            Array.Copy(sigBytes, sigBytesOffset, sig.iSeedInfo, 0, sig.iSeedInfoLen);
             sigBytesOffset += sig.iSeedInfoLen;
 //        Console.Error.Write("iSeedInfo: " + Hex.toHexString(sig.iSeedInfo));
 
             sig.cvInfo = new byte[sig.cvInfoLen];
-            System.Array.Copy(sigBytes, sigBytesOffset, sig.cvInfo, 0, sig.cvInfoLen);
+            Array.Copy(sigBytes, sigBytesOffset, sig.cvInfo, 0, sig.cvInfoLen);
             sigBytesOffset += sig.cvInfoLen;
 
             /* Read the proofs */
@@ -1058,13 +1035,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                     sig.proofs[t] = new Signature2.Proof2(this);
                     sig.proofs[t].seedInfoLen = seedInfoLen;
                     sig.proofs[t].seedInfo = new byte[sig.proofs[t].seedInfoLen];
-                    System.Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].seedInfo, 0, sig.proofs[t].seedInfoLen);
+                    Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].seedInfo, 0, sig.proofs[t].seedInfoLen);
                     sigBytesOffset += sig.proofs[t].seedInfoLen;
 
                     uint P_t = sig.challengeP[IndexOf(sig.challengeC, numOpenedRounds, t)];
                     if (P_t != (numMPCParties - 1))
                     {
-                        System.Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].aux, 0, andSizeBytes);
+                        Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].aux, 0, andSizeBytes);
                         sigBytesOffset += andSizeBytes;
                         if (!ArePaddingBitsZero(sig.proofs[t].aux, 3 * numRounds * numSboxes))
                         {
@@ -1073,11 +1050,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                         }
                     }
 
-                    System.Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].input, 0, stateSizeBytes);
+                    Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].input, 0, stateSizeBytes);
                     sigBytesOffset += stateSizeBytes;
 
                     int msgsByteLength = andSizeBytes;
-                    System.Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].msgs, 0, msgsByteLength);
+                    Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].msgs, 0, msgsByteLength);
                     sigBytesOffset += msgsByteLength;
                     int msgsBitLength = 3 * numRounds * numSboxes;
                     if (!ArePaddingBitsZero(sig.proofs[t].msgs, msgsBitLength))
@@ -1086,7 +1063,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                         return -1;
                     }
 
-                    System.Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].C, 0, digestSizeBytes);
+                    Array.Copy(sigBytes, sigBytesOffset, sig.proofs[t].C, 0, digestSizeBytes);
                     sigBytesOffset += digestSizeBytes;
                 }
             }
@@ -1112,7 +1089,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
         public void crypto_sign(byte[] sm, byte[] m, byte[] sk)
         {
             picnic_sign(sk, m, sm);
-            System.Array.Copy(m, 0, sm, 4, m.Length);
+            Array.Copy(m, 0, sm, 4, m.Length);
             sm = Arrays.CopyOfRange(sm, 0, signatureLength);
         }
 
@@ -1121,11 +1098,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             //todo unify conversion
 
             byte[] data_bytes = new byte[PICNIC_MAX_LOWMC_BLOCK_SIZE];
-            System.Array.Copy(sk, 1, data_bytes, 0, stateSizeBytes);
+            Array.Copy(sk, 1, data_bytes, 0, stateSizeBytes);
             byte[] ciphertext_bytes = new byte[PICNIC_MAX_LOWMC_BLOCK_SIZE];
-            System.Array.Copy(sk, 1 + stateSizeBytes, ciphertext_bytes, 0, stateSizeBytes);
+            Array.Copy(sk, 1 + stateSizeBytes, ciphertext_bytes, 0, stateSizeBytes);
             byte[] plaintext_bytes = new byte[PICNIC_MAX_LOWMC_BLOCK_SIZE];
-            System.Array.Copy(sk, 1 + 2 * stateSizeBytes, plaintext_bytes, 0, stateSizeBytes);
+            Array.Copy(sk, 1 + 2 * stateSizeBytes, plaintext_bytes, 0, stateSizeBytes);
             uint[] data = new uint[stateSizeWords];
             uint[] ciphertext = new uint[stateSizeWords];
             uint[] plaintext = new uint[stateSizeWords];
@@ -1134,7 +1111,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             Pack.LE_To_UInt32(plaintext_bytes, 0, plaintext);
             Pack.LE_To_UInt32(ciphertext_bytes, 0, ciphertext);
 
-
             if (!is_picnic3(parameters))
             {
                 Signature sig = new Signature(this);
@@ -1187,10 +1163,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
             int sigByteIndex = sigOffset;
 
-            System.Array.Copy(challengeBits, 0, sigBytes, sigByteIndex, Utils.NumBytes(2 * numMPCRounds));
+            Array.Copy(challengeBits, 0, sigBytes, sigByteIndex, Utils.NumBytes(2 * numMPCRounds));
             sigByteIndex += Utils.NumBytes(2 * numMPCRounds);
 
-            System.Array.Copy(sig.salt, 0, sigBytes, sigByteIndex, saltSizeBytes);
+            Array.Copy(sig.salt, 0, sigBytes, sigByteIndex, saltSizeBytes);
 
             sigByteIndex += saltSizeBytes;
 
@@ -1198,23 +1174,23 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             {
                 int challenge = GetChallenge(challengeBits, i);
 
-                System.Array.Copy(proofs[i].view3Commitment, 0, sigBytes, sigByteIndex, digestSizeBytes);
+                Array.Copy(proofs[i].view3Commitment, 0, sigBytes, sigByteIndex, digestSizeBytes);
                 sigByteIndex += digestSizeBytes;
 
                 if (transform == TRANSFORM_UR)
                 {
                     int view3UnruhLength = (challenge == 0) ? UnruhGWithInputBytes : UnruhGWithoutInputBytes;
-                    System.Array.Copy(proofs[i].view3UnruhG, 0, sigBytes, sigByteIndex, view3UnruhLength);
+                    Array.Copy(proofs[i].view3UnruhG, 0, sigBytes, sigByteIndex, view3UnruhLength);
                     sigByteIndex += view3UnruhLength;
                 }
 
-                System.Array.Copy(proofs[i].communicatedBits, 0, sigBytes, sigByteIndex, andSizeBytes);
+                Array.Copy(proofs[i].communicatedBits, 0, sigBytes, sigByteIndex, andSizeBytes);
                 sigByteIndex += andSizeBytes;
 
-                System.Array.Copy(proofs[i].seed1, 0, sigBytes, sigByteIndex, seedSizeBytes);
+                Array.Copy(proofs[i].seed1, 0, sigBytes, sigByteIndex, seedSizeBytes);
                 sigByteIndex += seedSizeBytes;
 
-                System.Array.Copy(proofs[i].seed2, 0, sigBytes, sigByteIndex, seedSizeBytes);
+                Array.Copy(proofs[i].seed2, 0, sigBytes, sigByteIndex, seedSizeBytes);
                 sigByteIndex += seedSizeBytes;
 
                 if (challenge == 1 || challenge == 2)
@@ -1235,7 +1211,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
         private int SerializeSignature2(Signature2 sig, byte[] sigBytes, int sigOffset)
         {
-
             /* Compute the number of bytes required for the signature */
             int bytesRequired = digestSizeBytes + saltSizeBytes; /* challenge and salt */
 
@@ -1266,16 +1241,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             }
 
             int sigByteIndex = sigOffset;
-            System.Array.Copy(sig.challengeHash, 0, sigBytes, sigByteIndex, digestSizeBytes);
+            Array.Copy(sig.challengeHash, 0, sigBytes, sigByteIndex, digestSizeBytes);
             sigByteIndex += digestSizeBytes;
 
-            System.Array.Copy(sig.salt, 0, sigBytes, sigByteIndex, saltSizeBytes);
+            Array.Copy(sig.salt, 0, sigBytes, sigByteIndex, saltSizeBytes);
             sigByteIndex += saltSizeBytes;
 
-            System.Array.Copy(sig.iSeedInfo, 0, sigBytes, sigByteIndex, sig.iSeedInfoLen);
+            Array.Copy(sig.iSeedInfo, 0, sigBytes, sigByteIndex, sig.iSeedInfoLen);
             sigByteIndex += sig.iSeedInfoLen;
 
-            System.Array.Copy(sig.cvInfo, 0, sigBytes, sigByteIndex, sig.cvInfoLen);
+            Array.Copy(sig.cvInfo, 0, sigBytes, sigByteIndex, sig.cvInfoLen);
             sigByteIndex += sig.cvInfoLen;
 
             /* Write the proofs */
@@ -1283,24 +1258,24 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             {
                 if (Contains(sig.challengeC, numOpenedRounds, t))
                 {
-                    System.Array.Copy(sig.proofs[t].seedInfo, 0, sigBytes, sigByteIndex, sig.proofs[t].seedInfoLen);
+                    Array.Copy(sig.proofs[t].seedInfo, 0, sigBytes, sigByteIndex, sig.proofs[t].seedInfoLen);
                     sigByteIndex += sig.proofs[t].seedInfoLen;
 
-                     uint P_t = sig.challengeP[IndexOf(sig.challengeC, numOpenedRounds, t)];
+                    uint P_t = sig.challengeP[IndexOf(sig.challengeC, numOpenedRounds, t)];
 
                     if (P_t != (numMPCParties - 1))
                     {
-                        System.Array.Copy(sig.proofs[t].aux, 0, sigBytes, sigByteIndex, andSizeBytes);
+                        Array.Copy(sig.proofs[t].aux, 0, sigBytes, sigByteIndex, andSizeBytes);
                         sigByteIndex += andSizeBytes;
                     }
 
-                    System.Array.Copy(sig.proofs[t].input, 0, sigBytes, sigByteIndex, stateSizeBytes);
+                    Array.Copy(sig.proofs[t].input, 0, sigBytes, sigByteIndex, stateSizeBytes);
                     sigByteIndex += stateSizeBytes;
 
-                    System.Array.Copy(sig.proofs[t].msgs, 0, sigBytes, sigByteIndex, andSizeBytes);
+                    Array.Copy(sig.proofs[t].msgs, 0, sigBytes, sigByteIndex, andSizeBytes);
                     sigByteIndex += andSizeBytes;
 
-                    System.Array.Copy(sig.proofs[t].C, 0, sigBytes, sigByteIndex, digestSizeBytes);
+                    Array.Copy(sig.proofs[t].C, 0, sigBytes, sigByteIndex, digestSizeBytes);
                     sigByteIndex += digestSizeBytes;
                 }
             }
@@ -1318,7 +1293,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             {
                 views[i] = new View[3];
             }
-            
+
             byte[][][] AS = new byte[numMPCRounds][][]; // numMPCRounds, numMPCParties, digestSizeBytes
             for (int i = 0; i < numMPCRounds; i++)
             {
@@ -1328,7 +1303,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                     AS[i][j] = new byte[digestSizeBytes];
                 }
             }
-            
+
             byte[][][] gs = new byte[numMPCRounds][][]; // numMPCRounds, 3, UnruhGWithInputBytes
             for (int i = 0; i < numMPCRounds; i++)
             {
@@ -1338,13 +1313,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                     gs[i][j] = new byte[UnruhGWithInputBytes];
                 }
             }
-            
-            
+
+
             /* Compute seeds for all parallel iterations */
             byte[] seeds = ComputeSeeds(privateKey, pubKey, plaintext, message);
             int seedLen = numMPCParties * seedSizeBytes;
 
-            System.Array.Copy(seeds, (seedLen) * (numMPCRounds), sig.salt, 0, saltSizeBytes);
+            Array.Copy(seeds, (seedLen) * (numMPCRounds), sig.salt, 0, saltSizeBytes);
 
             //Allocate a random tape (re-used per parallel iteration), and a temporary buffer
             Tape tape = new Tape(this);
@@ -1368,10 +1343,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                         return -1;
                     }
 
-                    System.Array.Copy(tmp, 0, view_byte, 0, stateSizeBytes);
-                    ZeroTrailingBits(view_byte, stateSizeBits);
+                    Array.Copy(tmp, 0, view_byte, 0, stateSizeBytes);
+                    Utils.ZeroTrailingBits(view_byte, stateSizeBits);
                     Pack.LE_To_UInt32(view_byte, 0, views[k][j].inputShare);
-                    System.Array.Copy(tmp, stateSizeBytes, tape.tapes[j], 0, andSizeBytes);
+                    Array.Copy(tmp, stateSizeBytes, tape.tapes[j], 0, andSizeBytes);
                 }
 
                 // Now set third party's wires. The random bits are from the seed, the input is
@@ -1439,7 +1414,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 (transform != TRANSFORM_UR) ? null : gs[i]); //todo check if
             }
 
-
             return 0;
         }
 
@@ -1449,18 +1423,18 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
         {
             if (challenge == 0)
             {
-                System.Array.Copy(seeds, seedsOffset + 0 * seedSizeBytes, proof.seed1, 0, seedSizeBytes);
-                System.Array.Copy(seeds, seedsOffset + 1 * seedSizeBytes, proof.seed2, 0, seedSizeBytes);
+                Array.Copy(seeds, seedsOffset + 0 * seedSizeBytes, proof.seed1, 0, seedSizeBytes);
+                Array.Copy(seeds, seedsOffset + 1 * seedSizeBytes, proof.seed2, 0, seedSizeBytes);
             }
             else if (challenge == 1)
             {
-                System.Array.Copy(seeds, seedsOffset + 1 * seedSizeBytes, proof.seed1, 0, seedSizeBytes);
-                System.Array.Copy(seeds, seedsOffset + 2 * seedSizeBytes, proof.seed2, 0, seedSizeBytes);
+                Array.Copy(seeds, seedsOffset + 1 * seedSizeBytes, proof.seed1, 0, seedSizeBytes);
+                Array.Copy(seeds, seedsOffset + 2 * seedSizeBytes, proof.seed2, 0, seedSizeBytes);
             }
             else if (challenge == 2)
             {
-                System.Array.Copy(seeds, seedsOffset + 2 * seedSizeBytes, proof.seed1, 0, seedSizeBytes);
-                System.Array.Copy(seeds, seedsOffset + 0 * seedSizeBytes, proof.seed2, 0, seedSizeBytes);
+                Array.Copy(seeds, seedsOffset + 2 * seedSizeBytes, proof.seed1, 0, seedSizeBytes);
+                Array.Copy(seeds, seedsOffset + 0 * seedSizeBytes, proof.seed2, 0, seedSizeBytes);
             }
             else
             {
@@ -1469,16 +1443,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
             if (challenge == 1 || challenge == 2)
             {
-                System.Array.Copy(views[2].inputShare, 0, proof.inputShare, 0, stateSizeBytes);
+                Array.Copy(views[2].inputShare, 0, proof.inputShare, 0, stateSizeBytes);
             }
 
-            System.Array.Copy(views[(challenge + 1) % 3].communicatedBits, 0, proof.communicatedBits, 0, andSizeBytes);
+            Array.Copy(views[(challenge + 1) % 3].communicatedBits, 0, proof.communicatedBits, 0, andSizeBytes);
 
-            System.Array.Copy(commitments[(challenge + 2) % 3], 0, proof.view3Commitment, 0, digestSizeBytes);
+            Array.Copy(commitments[(challenge + 2) % 3], 0, proof.view3Commitment, 0, digestSizeBytes);
             if (transform == TRANSFORM_UR)
             {
                 int view3UnruhLength = (challenge == 0) ? UnruhGWithInputBytes : UnruhGWithoutInputBytes;
-                System.Array.Copy(gs[(challenge + 2) % 3], 0, proof.view3UnruhG, 0, view3UnruhLength);
+                Array.Copy(gs[(challenge + 2) % 3], 0, proof.view3UnruhG, 0, view3UnruhLength);
             }
         }
 
@@ -1652,7 +1626,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
             for (int i = 0; i < 3; i++)
             {
-                System.Array.Copy(slab, (3 + i) * stateSizeWords, views[i].outputShare, 0, stateSizeWords);
+                Array.Copy(slab, (3 + i) * stateSizeWords, views[i].outputShare, 0, stateSizeWords);
             }
         }
 
@@ -1730,7 +1704,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             rand.pos++;
         }
 
-
         private void mpc_xor(uint[] state, uint[] input, int len, int players)
         {
             for (int player = 0; player < players; player++)
@@ -1743,7 +1716,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             }
         }
 
-
         private void mpc_matrix_mul(uint[] output, int outputOffset, uint[] state, int stateOffset,
             uint[] matrix, int matrixOffset, int players)
         {
@@ -1764,7 +1736,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             }
         }
 
-
         private bool CreateRandomTape(byte[] seed, int seedOffset, byte[] salt,  uint roundNumber, uint playerNumber,
             byte[] tape, int tapeLen)
         {
@@ -1807,9 +1778,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             return allSeeds;
         }
 
-
-
-
         private void sign_picnic3(uint[] privateKey, uint[] pubKey, uint[] plaintext, byte[] message, Signature2 sig)
         {
             byte[] saltAndRoot = new byte[saltSizeBytes + seedSizeBytes];
@@ -1924,7 +1892,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             sig.cvInfo = treeCv.OpenMerkleTree(missingLeaves, (uint)missingLeavesSize, cvInfoLen);
             sig.cvInfoLen = cvInfoLen[0];
 
-            /* Reveal iSeeds for unopned rounds, those in {0..T-1} \ ChallengeC. */
+            /* Reveal iSeeds for unopened rounds, those in {0..T-1} \ ChallengeC. */
             sig.iSeedInfo = new byte[numMPCRounds * seedSizeBytes];
             sig.iSeedInfoLen = iSeedsTree.RevealSeeds(sig.challengeC, (uint)numOpenedRounds,
                 sig.iSeedInfo, numMPCRounds * seedSizeBytes);
@@ -1934,7 +1902,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             sig.proofs = new Signature2.Proof2[numMPCRounds];
             for (uint t = 0; t < numMPCRounds; t++)
             {
-                if (Contains(sig.challengeC, numOpenedRounds, (uint)t))
+                if (Contains(sig.challengeC, numOpenedRounds, t))
                 {
                     sig.proofs[t] = new Signature2.Proof2(this);
                     int P_index = IndexOf(sig.challengeC, numOpenedRounds, t);
@@ -1951,34 +1919,23 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                         GetAuxBits(sig.proofs[t].aux, tapes[t]);
                     }
 
-                    System.Array.Copy(inputs[t], 0, sig.proofs[t].input, 0, stateSizeBytes);
-                    System.Array.Copy(msgs[t].msgs[sig.challengeP[P_index]], 0, sig.proofs[t].msgs, 0, andSizeBytes);
-                    System.Array.Copy(C[t][sig.challengeP[P_index]], 0, sig.proofs[t].C, 0, digestSizeBytes);
+                    Array.Copy(inputs[t], 0, sig.proofs[t].input, 0, stateSizeBytes);
+                    Array.Copy(msgs[t].msgs[sig.challengeP[P_index]], 0, sig.proofs[t].msgs, 0, andSizeBytes);
+                    Array.Copy(C[t][sig.challengeP[P_index]], 0, sig.proofs[t].C, 0, digestSizeBytes);
                 }
             }
-
         }
 
-        static int IndexOf(uint[] list, int len, uint value)
+        private static int IndexOf(uint[] list, int len, uint value)
         {
-            for (int i = 0; i < len; i++)
-            {
-                if (list[i] == value)
-                {
-                    return i;
-                }
-            }
-
-            return -1;
+            return Array.IndexOf(list, value, 0, len);
         }
 
-
-
         private uint[] GetMissingLeavesList(uint[] challengeC)
         {
             uint missingLeavesSize = (uint)(numMPCRounds - numOpenedRounds);
             uint[] missingLeaves = new uint[missingLeavesSize];
-             uint pos = 0;
+            uint pos = 0;
 
             for (int i = 0; i < numMPCRounds; i++)
             {
@@ -2055,8 +2012,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             return position + 1;
         }
 
-
-
         private void ExpandChallengeHash(byte[] challengeHash, uint[] challengeC, uint[] challengeP)
         {
             // Populate C
@@ -2065,7 +2020,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             uint[] chunks = new uint[digestSizeBytes * 8 / System.Math.Min(bitsPerChunkC, bitsPerChunkP)];
             byte[] h = new byte[MAX_DIGEST_SIZE];
 
-            System.Array.Copy(challengeHash, 0, h, 0, digestSizeBytes);
+            Array.Copy(challengeHash, 0, h, 0, digestSizeBytes);
 
             uint countC = 0;
             while (countC < numOpenedRounds)
@@ -2137,8 +2092,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             digest.DoFinal(digest_arr, 0, digestSizeBytes);
         }
 
-
-
         private int SimulateOnline(uint[] maskedKey, Tape tape, uint[] tmp_shares,
             Msg msg, uint[] plaintext, uint[] pubKey)
         {
@@ -2169,7 +2122,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
                 xor_array(state, roundKey, state, 0, stateSizeWords); // state += roundKey
             }
 
-            if (!(SubarrayEquals(state, pubKey, stateSizeWords)))
+            if (!SubarrayEquals(state, pubKey, stateSizeWords))
             {
                 ret = -1;
             }
@@ -2335,15 +2288,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
         private void GetAuxBits(byte[] output, Tape tape)
         {
-            int last = numMPCParties - 1;
-            int pos = 0;
-            int n = stateSizeBits;
+            var lastTape = tape.tapes[numMPCParties - 1];
+            int n = stateSizeBits, pos = 0, tapePos = 0;
 
             for (int j = 0; j < numRounds; j++)
             {
+                tapePos += n;
+
                 for (int i = 0; i < n; i++)
                 {
-                    Utils.SetBit(output, pos++, Utils.GetBit(tape.tapes[last], n + n * 2 * j + i));
+                    Utils.SetBit(output, pos++, Utils.GetBit(lastTape, tapePos++));
                 }
             }
         }
@@ -2389,13 +2343,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
         static bool is_picnic3(int parameters)
         {
-            if (parameters == 7 /*Picnic3_L1*/ ||
-                parameters == 8 /*Picnic3_L3*/ ||
-                parameters == 9 /*Picnic3_L5*/ )
-            {
-                return true;
-            }
-            return false;
+            return parameters == 7 /*Picnic3_L1*/ ||
+                   parameters == 8 /*Picnic3_L3*/ ||
+                   parameters == 9 /*Picnic3_L5*/ ;
         }
 
         //todo return int;
@@ -2421,9 +2371,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             }
 
             buf[0] = (byte) parameters;
-            System.Array.Copy(data, 0, buf, 1, stateSizeBytes);
-            System.Array.Copy(ciphertext, 0, buf, 1 + stateSizeBytes, stateSizeBytes);
-            System.Array.Copy(plaintext, 0, buf, 1 + 2 * stateSizeBytes, stateSizeBytes);
+            Array.Copy(data, 0, buf, 1, stateSizeBytes);
+            Array.Copy(ciphertext, 0, buf, 1 + stateSizeBytes, stateSizeBytes);
+            Array.Copy(plaintext, 0, buf, 1 + 2 * stateSizeBytes, stateSizeBytes);
             return bytesRequired;
         }
 
@@ -2437,8 +2387,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             }
 
             buf[0] = (byte) parameters;
-            System.Array.Copy(ciphertext, 0, buf, 1, stateSizeBytes);
-            System.Array.Copy(plaintext, 0, buf, 1 + stateSizeBytes, stateSizeBytes);
+            Array.Copy(ciphertext, 0, buf, 1, stateSizeBytes);
+            Array.Copy(plaintext, 0, buf, 1 + stateSizeBytes, stateSizeBytes);
             return bytesRequired;
 
         }
@@ -2450,30 +2400,18 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             uint[] data = new uint[data_bytes.Length / 4];
             uint[] plaintext = new uint[plaintext_bytes.Length / 4];
             uint[] ciphertext = new uint[ciphertext_bytes.Length / 4];
-            byte[] temp = new byte[stateSizeBytes];
 
             // generate a private key
-            random.NextBytes(temp);
-            ZeroTrailingBits(temp, stateSizeBits);
-            System.Array.Copy(temp, 0, data_bytes, 0, temp.Length);
-
-            for (int i = 0; i < data.Length; i++)
-            {
-                data[i] = Pack.LE_To_UInt32(data_bytes, i * 4);
-            }
-
+            random.NextBytes(data_bytes, 0, stateSizeBytes);
+            Utils.ZeroTrailingBits(data_bytes, stateSizeBits);
+            Pack.LE_To_UInt32(data_bytes, 0, data);
 
             // generate a plaintext block
-            random.NextBytes(temp);
-            ZeroTrailingBits(temp, stateSizeBits);
-            System.Array.Copy(temp, 0, plaintext_bytes, 0, temp.Length);
-
-            for (int i = 0; i < plaintext.Length; i++)
-            {
-                plaintext[i] = Pack.LE_To_UInt32(plaintext_bytes, i * 4);
-            }
+            random.NextBytes(plaintext_bytes, 0, stateSizeBytes);
+            Utils.ZeroTrailingBits(plaintext_bytes, stateSizeBits);
+            Pack.LE_To_UInt32(plaintext_bytes, 0, plaintext);
 
-            // computer ciphertext
+            // compute ciphertext
             LowMCEnc(plaintext, ciphertext, data);
 
             //copy back to byte array
@@ -2482,15 +2420,14 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             Pack.UInt32_To_LE(ciphertext, ciphertext_bytes, 0);
         }
 
-
         private void LowMCEnc(uint[] plaintext, uint[] output, uint[] key)
         {
             uint[] roundKey = new uint[LOWMC_MAX_WORDS];
 
-            if (plaintext != (output))
+            if (plaintext != output)
             {
                 /* output will hold the intermediate state */
-                System.Array.Copy(plaintext, 0, output, 0, stateSizeWords);
+                Array.Copy(plaintext, 0, output, 0, stateSizeWords);
             }
 
             KMatricesWithPointer current = LowmcConstants.Instance.KMatrix(this, 0);
@@ -2514,7 +2451,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             }
         }
 
-
         private void Substitution(uint[] state)
         {
             for (int i = 0; i < numSboxes * 3; i += 3)
@@ -2551,47 +2487,35 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             matrix_mul_offset(output, 0, state, 0, matrix, matrixOffset);
         }
 
-        protected void matrix_mul_offset(uint[] output, int outputOffset,
-            uint[] state, int stateOffset,
-            uint[] matrix, int matrixOffset)
+        protected void matrix_mul_offset(uint[] output, int outputOffset, uint[] state, int stateOffset, uint[] matrix,
+            int matrixOffset)
         {
             // Use temp to correctly handle the case when state = output
-            uint prod;
             uint[] temp = new uint[LOWMC_MAX_WORDS];
             temp[stateSizeWords - 1] = 0;
             int wholeWords = stateSizeBits / WORD_SIZE_BITS;
 
             for (int i = 0; i < stateSizeBits; i++)
             {
-                prod = 0;
+                uint prod = 0;
                 for (int j = 0; j < wholeWords; j++)
                 {
                     int index = i * stateSizeWords + j;
-                    prod ^= (state[j + stateOffset] & matrix[matrixOffset + index]);
+                    prod ^= state[j + stateOffset] & matrix[matrixOffset + index];
                 }
 
                 for (int j = wholeWords * WORD_SIZE_BITS; j < stateSizeBits; j++)
                 {
                     int index = i * stateSizeWords * WORD_SIZE_BITS + j;
-                    uint bit = (Utils.GetBitFromWordArray(state, j + stateOffset * 32) &
-                               Utils.GetBitFromWordArray(matrix, matrixOffset * 32 + index));
+                    uint bit = Utils.GetBitFromWordArray(state, stateOffset * 32 + j)
+                             & Utils.GetBitFromWordArray(matrix, matrixOffset * 32 + index);
                     prod ^= bit;
                 }
 
-                Utils.SetBit(temp, i, (int)Utils.Parity32(prod));
-
+                Utils.SetBit(temp, i, Utils.Parity32(prod));
             }
 
-            System.Array.Copy(temp, 0, output, outputOffset, stateSizeWords);
-        }
-
-        private void ZeroTrailingBits(byte[] data, int bitLength)
-        {
-            int byteLength = Utils.NumBytes(bitLength);
-            for (int i = bitLength; i < byteLength * 8; i++)
-            {
-                Utils.SetBit(data, i, (byte) 0);
-            }
+            Array.Copy(temp, 0, output, outputOffset, stateSizeWords);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/crypto/src/pqc/crypto/picnic/Utils.cs b/crypto/src/pqc/crypto/picnic/Utils.cs
index a23985568..8e0bdc6ff 100644
--- a/crypto/src/pqc/crypto/picnic/Utils.cs
+++ b/crypto/src/pqc/crypto/picnic/Utils.cs
@@ -1,20 +1,20 @@
 namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 {
-    public class Utils
+    internal static class Utils
     {
-        protected internal static void Fill(uint[] buf, int from, int to, uint b)
+        internal static void Fill(uint[] buf, int from, int to, uint b)
         {
             for (int i = from; i < to; ++i)
             {
                 buf[i] = b;
             }
         }
-        protected internal static int NumBytes(int numBits)
+        internal static int NumBytes(int numBits)
         {
-            return (numBits == 0) ? 0 : ((numBits - 1) / 8 + 1);
+            return (numBits + 7) >> 3;
         }
 
-        protected internal static uint ceil_log2(uint x)
+        internal static uint ceil_log2(uint x)
         {
             if (x == 0)
             {
@@ -59,8 +59,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             return n;
         }
 
-
-        protected static int Parity(byte[] data, int len)
+        internal static int Parity(byte[] data, int len)
         {
             byte x = data[0];
 
@@ -81,7 +80,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             return y & 1;
         }
 
-        protected internal static uint Parity16(uint x)
+        internal static uint Parity16(uint x)
         {
             uint y = x ^ (x >> 1);
 
@@ -91,7 +90,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
             return y & 1;
         }
 
-        protected internal static uint Parity32(uint x)
+        internal static uint Parity32(uint x)
         {
             /* Compute parity of x using code from Section 5-2 of
              * H.S. Warren, *Hacker's Delight*, Pearson Education, 2003.
@@ -107,32 +106,32 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
 
 
         /* Set a specific bit in a byte array to a given value */
-        protected internal static void SetBitInWordArray(uint[] array, int bitNumber, uint val)
+        internal static void SetBitInWordArray(uint[] array, int bitNumber, uint val)
         {
-            SetBit(array, bitNumber, (int)val);
+            SetBit(array, bitNumber, val);
         }
 
         /* Get one bit from a 32-bit int array */
-        protected internal static uint GetBitFromWordArray(uint[] array, int bitNumber)
+        internal static uint GetBitFromWordArray(uint[] array, int bitNumber)
         {
             return GetBit(array, bitNumber);
         }
 
         /* Get one bit from a byte array */
-        internal protected static byte GetBit(byte[] array, int bitNumber)
+        internal static byte GetBit(byte[] array, int bitNumber)
         {
             int arrayPos = bitNumber >> 3, bitPos = (bitNumber & 7) ^ 7;
             return (byte)((array[arrayPos] >> bitPos) & 1);
         }
 
         /* Get one bit from a byte array */
-        internal protected static uint GetBit(uint[] array, int bitNumber)
+        internal static uint GetBit(uint[] array, int bitNumber)
         {
             int arrayPos = bitNumber >> 5, bitPos = (bitNumber & 31) ^ 7;
             return (array[arrayPos] >> bitPos) & 1;
         }
 
-        internal protected static void SetBit(byte[] array, int bitNumber, byte val)
+        internal static void SetBit(byte[] array, int bitNumber, byte val)
         {
             int arrayPos = bitNumber >> 3, bitPos = (bitNumber & 7) ^ 7;
             uint t = array[arrayPos];
@@ -142,13 +141,22 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic
         }
 
         /* Set a specific bit in a int array to a given value */
-        internal protected static void SetBit(uint[] array, int bitNumber, int val)
+        internal static void SetBit(uint[] array, int bitNumber, uint val)
         {
             int arrayPos = bitNumber >> 5, bitPos = (bitNumber & 31) ^ 7;
             uint t = array[arrayPos];
             t &= ~(1U << bitPos);
-            t |= (uint)val << bitPos;
+            t |= val << bitPos;
             array[arrayPos] = t;
         }
+
+        internal static void ZeroTrailingBits(byte[] data, int bitLength)
+        {
+            int partial = bitLength & 7;
+            if (partial != 0)
+            {
+                data[bitLength >> 3] &= (byte)(0xFF00 >> partial);
+            }
+        }
     }
 }