public void Pack(byte[] plain, byte[] tag) { byte[] cipher = new byte[NtagHelpers.NFC3D_AMIIBO_SIZE]; // Generate keys var tagKeys = GenerateKey(this.tag, plain); var dataKeys = GenerateKey(this.data, plain); // Init OpenSSL HMAC context HMac hmacCtx = new HMac(new Sha256Digest()); // Generate tag HMAC hmacCtx.Init(new KeyParameter(tagKeys.hmacKey)); hmacCtx.BlockUpdate(plain, 0x1D4, 0x34); hmacCtx.DoFinal(cipher, HMAC_POS_TAG); // Generate data HMAC hmacCtx.Init(new KeyParameter(dataKeys.hmacKey)); hmacCtx.BlockUpdate(plain, 0x029, 0x18B); // Data hmacCtx.BlockUpdate(cipher, HMAC_POS_TAG, 0x20); // Tag HMAC hmacCtx.BlockUpdate(plain, 0x1D4, 0x34); // Tag hmacCtx.DoFinal(cipher, HMAC_POS_DATA); // Encrypt dataKeys.Cipher(plain, cipher, true); // Convert back to hardware NtagHelpers.InternalToTag(cipher, tag); Array.Copy(plain, 0x208, tag, 0x208, 0x014); }
public bool Unpack(byte[] tag, byte[] plain) { byte[] internalBytes = NtagHelpers.GetInternalTag(tag); // Generate keys KeygenDerivedkeys dataKeys = GenerateKey(this.data, internalBytes); KeygenDerivedkeys tagKeys = GenerateKey(this.tag, internalBytes); // Decrypt dataKeys.Cipher(internalBytes, plain, false); // Init OpenSSL HMAC context HMac hmacCtx = new HMac(new Sha256Digest()); // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! hmacCtx.Init(new KeyParameter(tagKeys.hmacKey)); hmacCtx.BlockUpdate(plain, 0x1D4, 0x34); hmacCtx.DoFinal(plain, HMAC_POS_TAG); // Regenerate data HMAC hmacCtx.Init(new KeyParameter(dataKeys.hmacKey)); hmacCtx.BlockUpdate(plain, 0x029, 0x1DF); hmacCtx.DoFinal(plain, HMAC_POS_DATA); Array.Copy(tag, 0x208, plain, 0x208, 0x014); return (NativeHelpers.MemCmp(plain, internalBytes, HMAC_POS_DATA, 32) && NativeHelpers.MemCmp(plain, internalBytes, HMAC_POS_TAG, 32)); }