// Separate IV and ciptertext/tag combination let ivCiphertextTagB64 = "2wLsVLuOJFX1pfwwjoLhQrW7f/86AefyZ7FwJEhJVIpU+iG2EITzushCpDRxgqK2cwVYvfNt7KFZ39obMMmIqhrDCIeifzs="; let ivCiphertextTag = sjcl.codec.base64.toBits(ivCiphertextTagB64); let iv = sjcl.bitArray.bitSlice(ivCiphertextTag, 0, GCM_NONCE_LENGTH); let ciphertextTag = sjcl.bitArray.bitSlice(ivCiphertextTag, GCM_NONCE_LENGTH);
// Derive key via SHA256 let key = sjcl.hash.sha256.hash("my password");
// Decrypt let cipher = new sjcl.cipher.aes(key); let plaintext = sjcl.mode.gcm.decrypt( cipher, ciphertextTag, iv, null, GCM_TAG_LENGTH ); //let plaintext = sjcl.mode.gcm.decrypt(cipher, ciphertextTag, iv) // works also; here the defaults for the AAD ([]) and the tag size (16 bytes) are applied console.log(sjcl.codec.utf8String.fromBits(plaintext));
let bkey = sjcl.codec.base64.toBits(key); let bdata = sjcl.codec.base64.toBits(cipherText); let cipher = new sjcl.cipher.aes(bkey);
let aad = sjcl.bitArray.bitSlice(bdata, 0, GCM_AAD_LENGTH); let iv = sjcl.bitArray.bitSlice(aad, GCM_NONCE_LENGTH * -1); let tag = sjcl.bitArray.bitSlice(bdata, GCM_TAG_LENGTH * -1); let data = sjcl.bitArray.bitSlice(bdata, GCM_AAD_LENGTH); let decryptedContent = "";
let decbits = sjcl.mode.gcm.decrypt(cipher, data, iv, aad, GCM_TAG_LENGTH); decryptedContent = sjcl.codec.utf8String.fromBits(decbits); console.log("decryptedContent", decryptedContent);
public (byte[], byte[]) Encrypt(byte[] dataToEncrypt, byte[] key, byte[] nonce, byte[] associatedData) { // these will be filled during the encryption byte[] tag = newbyte[16];
//生成一个12位的随机Iv var iv = sjcl.random.randomWords(3, 0);
var key = sjcl.codec.hex.toBits(this.keyString); var cipher = new sjcl.cipher.aes(key); var data = sjcl.codec.utf8String.toBits(params); var enc = sjcl.mode.gcm.encrypt(cipher, data, iv, {}, 128);
//把得到的Iv,也就是Mac和加密后的内容连接起来 var concatbitArray = sjcl.bitArray.concat(iv, enc);
//再转成Base64发送 var conString = sjcl.codec.base64.fromBits(concatbitArray); return conString; }
publicstaticdecryptor(content) {
//先从Base64转hexstring var bitArray = sjcl.codec.base64.toBits(content); var bitArrayCopy = bitArray.slice(0);
//取前3位,取出Iv var ivdec = bitArrayCopy.slice(0, 3);
//后面的为密文 var encryptedBitArray = bitArray.slice(3); var key = sjcl.codec.hex.toBits(this.keyString); let cipher = new sjcl.cipher.aes(key); var data = sjcl.mode.gcm.decrypt(cipher, encryptedBitArray, ivdec, {}, 128); var str = sjcl.codec.utf8String.fromBits(data); return str; }
using (var cipherStream = new MemoryStream(encryptedMessage)) using (var cipherReader = new BinaryReader(cipherStream)) { //Grab Payload var nonSecretPayload = cipherReader.ReadBytes(nonSecretPayloadLength);
//Grab Nonce var nonce = cipherReader.ReadBytes(_nonceSize / 8);
var cipher = new GcmBlockCipher(new AesEngine()); var parameters = new AeadParameters(new KeyParameter(key), _macSize, nonce, nonSecretPayload); cipher.Init(false, parameters);
//Decrypt Cipher Text var cipherText = cipherReader.ReadBytes(encryptedMessage.Length - nonSecretPayloadLength - nonce.Length); var plainText = newbyte[cipher.GetOutputSize(cipherText.Length)];
var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0); cipher.DoFinal(plainText, len);
//Using random nonce large enough not to repeat var nonce = newbyte[_nonceSize / 8]; _random.NextBytes(nonce, 0, nonce.Length);
var cipher = new GcmBlockCipher(new AesEngine()); var parameters = new AeadParameters(new KeyParameter(key), _macSize, nonce, nonSecretPayload); cipher.Init(true, parameters);
//Generate Cipher Text With Auth Tag var cipherText = newbyte[cipher.GetOutputSize(messageToEncrypt.Length)]; var len = cipher.ProcessBytes(messageToEncrypt, 0, messageToEncrypt.Length, cipherText, 0); cipher.DoFinal(cipherText, len);
//Assemble Message using (var combinedStream = new MemoryStream()) { using (var binaryWriter = new BinaryWriter(combinedStream)) { //Prepend Authenticated Payload binaryWriter.Write(nonSecretPayload); //Prepend Nonce binaryWriter.Write(nonce); //Write Cipher Text binaryWriter.Write(cipherText); }
return combinedStream.ToArray(); } }
privatevoidCheckKey(byte[] key) { if (key == null || key.Length != _keySize / 8) { thrownew ArgumentException( String.Format("Key needs to be {0} bit! actual:{1}", _keySize, key?.Length * 8), "key"); } }