private uint[] sjclDecryptAes() { int L; int ivl = this.sjclBitLength(this.uint32IV) / 8; int ol = this.ctBitLength; uint[] outX = this.uint32Out; uint[] tag = this.uint32Tag; ol = (ol - this.tagSize) / 8;//out length (byte) if (ivl < 7) { throw new Exception("IV must be at least 7 bytes"); } // compute the length of the length uint olx = (uint)ol; for (L = 2; L < 4 && (olx >> 8 * L) != 0; L++) { } if (L < 15 - ivl) { L = 15 - ivl; } long[] ivx = this.sjclClampForIV(this.uint32IV, 8 * (15 - L)); // decrypt SJCLResult ret = this.sjclCCMCounterMode(outX, ivx, tag, L); // check the tag uint[] tag2 = this.sjclCCMComputeTag(ret.Data, ivx, L); if (this.sjclEqual(ret.Tag, tag2) == false) { throw new Exception("tag doesn't match"); } return(ret.Data); }
private SJCLResult sjclCCMCounterMode(uint[] aOut, long[] aIV, uint[] aTag, int aL) { int bl = this.ctBitLength - this.tagSize;//original data size int l = aOut.Length; // start the ctr long partial = this.sjclPartialLong(8, (uint)(aL - 1), 0); long[] partialAr = new long[] { partial }; //one object array uint[] temp1 = this.sjclConcat(partialAr, aIV); uint[] temp2 = new uint[3]; //{0,0,0} uint[] tempMerge = new uint[temp1.Length + temp2.Length]; Array.Copy(temp1, 0, tempMerge, 0, temp1.Length); Array.Copy(temp2, 0, tempMerge, temp1.Length, temp2.Length);//merge uint[] ctr = new uint[4]; Array.Copy(tempMerge, 0, ctr, 0, ctr.Length); // en/decrypt the tag uint[] cryptCtr = this.sjclCrypt(ctr, false); uint[] tag = this.sjclXOR4(aTag, cryptCtr); // en/decrypt the data if (l == 0) {//data size is 0 return(new SJCLResult(tag, new uint[0])); } uint[] enc; uint[] aoutx = new uint[aOut.Length + 3]; Array.Copy(aOut, 0, aoutx, 0, aOut.Length);//extend for (int i = 0; i < l; i += 4) { ctr[3]++; enc = this.sjclCrypt(ctr, false); aoutx[i] ^= enc[0]; aoutx[i + 1] ^= enc[1]; aoutx[i + 2] ^= enc[2]; aoutx[i + 3] ^= enc[3]; } SJCLResult ret = new SJCLResult(tag, this.sjclClamp(aoutx, bl)); return(ret); }