public static UInt256 ComputeHash(IChainState chainState) { using (var sha256 = new SHA256Managed()) { // add each unspent tx to hash foreach (var unspentTx in chainState.ReadUnspentTransactions()) { var unspentTxBytes = DataEncoder.EncodeUnspentTx(unspentTx); sha256.TransformBlock(unspentTxBytes, 0, unspentTxBytes.Length, unspentTxBytes, 0); } // finalize hash sha256.TransformFinalBlock(new byte[0], 0, 0); // hash again to return double-hashed utxo committment return new UInt256(SHA256Static.ComputeHash(sha256.Hash)); } }
public static string Calculate_Hash(string fileName) { long read = 0; var r = -1; const long bytesToRead = 100 * 1024 * 1024; const int bufferSize = 4096; var buffer = new byte[bufferSize]; var sha = new SHA256Managed(); using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { while (read <= bytesToRead && r != 0) { read += (r = stream.Read(buffer, 0, bufferSize)); sha.TransformBlock(buffer, 0, r, null, 0); } } sha.TransformFinalBlock(buffer, 0, 0); return string.Join("", sha.Hash.Select(x => x.ToString("x2"))); }
/// <summary> /// Generate a Mavlink Packet and write to serial /// </summary> /// <param name="messageType">type number = MAVLINK_MSG_ID</param> /// <param name="indata">struct of data</param> void generatePacket(int messageType, object indata) { if (!BaseStream.IsOpen) { return; } if (ReadOnly) { // allow these messages if (messageType == (byte) MAVLink.MAVLINK_MSG_ID.MISSION_REQUEST_LIST || messageType == (byte) MAVLink.MAVLINK_MSG_ID.MISSION_REQUEST_PARTIAL_LIST || messageType == (byte) MAVLink.MAVLINK_MSG_ID.MISSION_REQUEST || messageType == (byte) MAVLink.MAVLINK_MSG_ID.PARAM_REQUEST_LIST || messageType == (byte) MAVLink.MAVLINK_MSG_ID.PARAM_REQUEST_READ || messageType == (byte) MAVLink.MAVLINK_MSG_ID.RALLY_FETCH_POINT || messageType == (byte) MAVLink.MAVLINK_MSG_ID.FENCE_FETCH_POINT ) { } else { return; } } lock (objlock) { byte[] data = MavlinkUtil.StructureToByteArray(indata); byte[] packet = new byte[0]; int i = 0; if (!mavlinkv2) { //Console.WriteLine(DateTime.Now + " PC Doing req "+ messageType + " " + this.BytesToRead); packet = new byte[data.Length + 6 + 2]; packet[0] = MAVLINK_STX_MAVLINK1; packet[1] = (byte) data.Length; packet[2] = (byte) packetcount; packetcount++; packet[3] = gcssysid; packet[4] = (byte) MAV_COMPONENT.MAV_COMP_ID_MISSIONPLANNER; packet[5] = (byte)messageType; i = 6; foreach (byte b in data) { packet[i] = b; i++; } ushort checksum = MavlinkCRC.crc_calculate(packet, packet[1] + 6); checksum = MavlinkCRC.crc_accumulate(MAVLINK_MESSAGE_CRCS[(uint)messageType], checksum); byte ck_a = (byte) (checksum & 0xFF); ///< High byte byte ck_b = (byte) (checksum >> 8); ///< Low byte packet[i] = ck_a; i += 1; packet[i] = ck_b; i += 1; } else if (mavlinkv2) { packet = new byte[data.Length + MAVLINK_NUM_HEADER_BYTES + MAVLINK_NUM_CHECKSUM_BYTES + MAVLINK_SIGNATURE_BLOCK_LEN]; packet[0] = MAVLINK_STX ; packet[1] = (byte)data.Length; packet[2] = 0; // incompat if (MAV.signing) // current mav packet[2] |= MAVLINK_IFLAG_SIGNED; packet[3] = 0; // compat packet[4] = (byte)packetcount; packetcount++; packet[5] = gcssysid; packet[6] = (byte)MAV_COMPONENT.MAV_COMP_ID_MISSIONPLANNER; packet[7] = (byte)(messageType & 0xff); packet[8] = (byte)((messageType >> 8) & 0xff); packet[9] = (byte)((messageType >> 16) & 0xff); i = 10; foreach (byte b in data) { packet[i] = b; i++; } ushort checksum = MavlinkCRC.crc_calculate(packet, packet[1] + MAVLINK_NUM_HEADER_BYTES); checksum = MavlinkCRC.crc_accumulate(MAVLINK_MESSAGE_CRCS[(uint)messageType], checksum); byte ck_a = (byte)(checksum & 0xFF); ///< High byte byte ck_b = (byte)(checksum >> 8); ///< Low byte packet[i] = ck_a; i += 1; packet[i] = ck_b; i += 1; if (MAV.signing) { //https://docs.google.com/document/d/1ETle6qQRcaNWAmpG2wz0oOpFKSF_bcTmYMQvtTGI8ns/edit /* 8 bits of link ID 48 bits of timestamp 48 bits of signature */ // signature = sha256_48(secret_key + header + payload + CRC + link-ID + timestamp) var timestamp = (UInt64) ((DateTime.UtcNow - new DateTime(2015, 1, 1)).TotalMilliseconds*1000); var timebytes = BitConverter.GetBytes(timestamp); var sig = new byte[7]; // 13 includes the outgoing hash sig[0] = 0; Array.Copy(timebytes, 0, sig, 1, 6); // timestamp //Console.WriteLine("gen linkid {0}, time {1} {2} {3} {4} {5} {6}", sig[0], sig[1], sig[2], sig[3], sig[4], sig[5], sig[6]); using (SHA256Managed signit = new SHA256Managed()) { signit.TransformBlock(signingKey, 0, signingKey.Length, null, 0); signit.TransformBlock(packet, 0, i, null, 0); signit.TransformFinalBlock(sig, 0, sig.Length); var ctx = signit.Hash; // trim to 48 Array.Resize(ref ctx, 6); foreach (byte b in sig) { packet[i] = b; i++; } foreach (byte b in ctx) { packet[i] = b; i++; } } } } if (BaseStream.IsOpen) { BaseStream.Write(packet, 0, i); _bytesSentSubj.OnNext(i); } try { if (logfile != null && logfile.CanWrite) { lock (logfile) { byte[] datearray = BitConverter.GetBytes( (UInt64) ((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds*1000)); Array.Reverse(datearray); logfile.Write(datearray, 0, datearray.Length); logfile.Write(packet, 0, i); } } } catch { } } }
/// <summary> /// Serial Reader to read mavlink packets. POLL method /// </summary> /// <returns></returns> public MAVLinkMessage readPacket() { byte[] buffer = new byte[MAVLINK_MAX_PACKET_LEN + 25]; int count = 0; int length = 0; int readcount = 0; BaseStream.ReadTimeout = 1200; // 1200 ms between chars - the gps detection requires this. DateTime start = DateTime.Now; //Console.WriteLine(DateTime.Now.Millisecond + " SR0 " + BaseStream.BytesToRead); lock (readlock) { lastbad = new byte[2]; //Console.WriteLine(DateTime.Now.Millisecond + " SR1 " + BaseStream.BytesToRead); while (BaseStream.IsOpen || logreadmode) { try { if (readcount > 300) { log.Info("MAVLink readpacket No valid mavlink packets"); break; } readcount++; if (logreadmode) { buffer = readlogPacketMavlink().buffer; if (buffer.Length == 0) return new MAVLinkMessage(); } else { // time updated for internal reference MAV.cs.datetime = DateTime.Now; DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout); // Console.WriteLine(DateTime.Now.Millisecond + " SR1a " + BaseStream.BytesToRead); while (BaseStream.IsOpen && BaseStream.BytesToRead <= 0) { if (DateTime.Now > to) { log.InfoFormat("MAVLINK: 1 wait time out btr {0} len {1}", BaseStream.BytesToRead, length); throw new TimeoutException("Timeout"); } System.Threading.Thread.Sleep(1); //Console.WriteLine(DateTime.Now.Millisecond + " SR0b " + BaseStream.BytesToRead); } //Console.WriteLine(DateTime.Now.Millisecond + " SR1a " + BaseStream.BytesToRead); if (BaseStream.IsOpen) { BaseStream.Read(buffer, count, 1); if (rawlogfile != null && rawlogfile.CanWrite) rawlogfile.WriteByte(buffer[count]); } //Console.WriteLine(DateTime.Now.Millisecond + " SR1b " + BaseStream.BytesToRead); } } catch (Exception e) { log.Info("MAVLink readpacket read error: " + e.ToString()); break; } // check if looks like a mavlink packet and check for exclusions and write to console if (buffer[0] != 0xfe && buffer[0] != 'U' && buffer[0] != 0xfd) { if (buffer[0] >= 0x20 && buffer[0] <= 127 || buffer[0] == '\n' || buffer[0] == '\r') { // check for line termination if (buffer[0] == '\r' || buffer[0] == '\n') { // check new line is valid if (buildplaintxtline.Length > 3) plaintxtline = buildplaintxtline; // reset for next line buildplaintxtline = ""; } TCPConsole.Write(buffer[0]); Console.Write((char)buffer[0]); buildplaintxtline += (char)buffer[0]; } _bytesReceivedSubj.OnNext(1); count = 0; lastbad[0] = lastbad[1]; lastbad[1] = buffer[0]; buffer[1] = 0; continue; } // reset count on valid packet readcount = 0; //Console.WriteLine(DateTime.Now.Millisecond + " SR2 " + BaseStream.BytesToRead); mavlinkv2 = buffer[0] == MAVLINK_STX ? true : false; int headerlength = mavlinkv2 ? MAVLINK_CORE_HEADER_LEN : MAVLINK_CORE_HEADER_MAVLINK1_LEN; int headerlengthstx = headerlength + 1; // check for a header if (buffer[0] == 0xfe || buffer[0] == 0xfd || buffer[0] == 'U') { // if we have the header, and no other chars, get the length and packet identifiers if (count == 0 && !logreadmode) { DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout); while (BaseStream.IsOpen && BaseStream.BytesToRead < headerlength) { if (DateTime.Now > to) { log.InfoFormat("MAVLINK: 2 wait time out btr {0} len {1}", BaseStream.BytesToRead, length); throw new Exception("Timeout"); } System.Threading.Thread.Sleep(1); } int read = BaseStream.Read(buffer, 1, headerlength); count = read; if (rawlogfile != null && rawlogfile.CanWrite) rawlogfile.Write(buffer, 1, read); } // packet length if (buffer[0] == 0xfd) { length = buffer[1] + headerlengthstx + 2 - 2; // data + header + checksum - magic - length if ((buffer[2] & MAVLINK_IFLAG_SIGNED) > 0) { length += MAVLINK_SIGNATURE_BLOCK_LEN; } } else { length = buffer[1] + headerlengthstx + 2 - 2; // data + header + checksum - U - length } if (count >= headerlength || logreadmode) { try { if (logreadmode) { } else { DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout); while (BaseStream.IsOpen && BaseStream.BytesToRead < (length - count)) { if (DateTime.Now > to) { log.InfoFormat("MAVLINK: 3 wait time out btr {0} len {1}", BaseStream.BytesToRead, length); break; } System.Threading.Thread.Sleep(1); } if (BaseStream.IsOpen) { int read = BaseStream.Read(buffer, headerlengthstx, length - (headerlengthstx-2)); if (rawlogfile != null && rawlogfile.CanWrite) { // write only what we read, temp is the whole packet, so 6-end rawlogfile.Write(buffer, headerlengthstx, read); } } } count = length + 2; } catch { break; } break; } } count++; if (count == 299) break; } //Console.WriteLine(DateTime.Now.Millisecond + " SR3 " + BaseStream.BytesToRead); } // end readlock // resize the packet to the correct length Array.Resize<byte>(ref buffer, count); // add byte count _bytesReceivedSubj.OnNext(buffer.Length); // update bps statistics if (bpstime.Second != DateTime.Now.Second) { long btr = 0; if (BaseStream != null && BaseStream.IsOpen) { btr = BaseStream.BytesToRead; } else if (logreadmode) { btr = logplaybackfile.BaseStream.Length - logplaybackfile.BaseStream.Position; } Console.Write("bps {0} loss {1} left {2} mem {3} \n", bps1, MAV.synclost, btr, System.GC.GetTotalMemory(false)/1024/1024.0); bps2 = bps1; // prev sec bps1 = 0; // current sec bpstime = DateTime.Now; } bps1 += buffer.Length; if (buffer.Length == 0) return new MAVLinkMessage(); MAVLinkMessage message = new MAVLinkMessage(buffer); uint msgid = message.msgid; message_info msginfo; msginfo = MAVLINK_MESSAGE_INFOS.SingleOrDefault(p => p.msgid == msgid); // calc crc var sigsize = (message.sig != null) ? MAVLINK_SIGNATURE_BLOCK_LEN : 0; ushort crc = MavlinkCRC.crc_calculate(buffer, message.Length - sigsize-MAVLINK_NUM_CHECKSUM_BYTES); // calc extra bit of crc for mavlink 1.0/2.0 if (message.header == 0xfe || message.header == 0xfd) { crc = MavlinkCRC.crc_accumulate(msginfo.crc, crc); } // check message length vs table if (message.payloadlength != msginfo.length) { if (msginfo.length == 0) // pass for unknown packets { log.InfoFormat("unknown packet type {0}", message.msgid); } else { log.InfoFormat("Mavlink Bad Packet (Len Fail) len {0} pkno {1}", buffer.Length, message.msgid); if (buffer.Length == 11 && message.header == 'U' && message.msgid == 0) // check for 0.9 hb packet { string messagehb = "Mavlink 0.9 Heartbeat, Please upgrade your AP, This planner is for Mavlink 1.0\n\n"; Console.WriteLine(messagehb); if (logreadmode) logplaybackfile.BaseStream.Seek(0, SeekOrigin.End); throw new Exception(messagehb); } return new MAVLinkMessage(); } } // check crc if ((message.crc16 >> 8) != (crc >> 8) || (message.crc16 & 0xff) != (crc & 0xff)) { if (message.msgid != -1 && buffer.Length > 5 && msginfo.name != null) log.InfoFormat("Mavlink Bad Packet (crc fail) len {0} crc {1} vs {4} pkno {2} {3}", buffer.Length, crc, message.msgid, msginfo.name.ToString(), message.crc16); if (logreadmode) log.InfoFormat("bad packet pos {0} ", logplaybackfile.BaseStream.Position); return new MAVLinkMessage(); } byte sysid = message.sysid; byte compid = message.compid; byte packetSeqNo = message.seq; //check if sig was included in packet, and we are not ignoring the signature (signing isnt checked else we wont enable signing) if (message.sig != null && !MAVlist[sysid,compid].signingignore) { using (SHA256Managed signit = new SHA256Managed()) { signit.TransformBlock(signingKey, 0, signingKey.Length, null, 0); signit.TransformFinalBlock(message.buffer, 0, message.Length - MAVLINK_SIGNATURE_BLOCK_LEN + 7); var ctx = signit.Hash; // trim to 48 Array.Resize(ref ctx, 6); //Console.WriteLine("linkid {0}, time {1} {2} {3} {4} {5} {6} - {7}", message.sig[0], message.sig[1], message.sig[2], message.sig[3], message.sig[4], message.sig[5], message.sig[6], message.sigTimestamp); for (int i = 0; i < ctx.Length; i++) { if (ctx[i] != message.sig[7 + i]) { log.InfoFormat("Packet failed signature but passed crc"); return new MAVLinkMessage(); } } MAVlist[sysid, compid].linkid = message.sig[0]; enableSigning(); } } // packet is now verified // update packet loss statistics if (!logreadmode && MAVlist[sysid, compid].packetlosttimer.AddSeconds(5) < DateTime.Now) { MAVlist[sysid, compid].packetlosttimer = DateTime.Now; MAVlist[sysid, compid].packetslost = (MAVlist[sysid, compid].packetslost*0.8f); MAVlist[sysid, compid].packetsnotlost = (MAVlist[sysid, compid].packetsnotlost*0.8f); } else if (logreadmode && MAVlist[sysid, compid].packetlosttimer.AddSeconds(5) < lastlogread) { MAVlist[sysid, compid].packetlosttimer = lastlogread; MAVlist[sysid, compid].packetslost = (MAVlist[sysid, compid].packetslost*0.8f); MAVlist[sysid, compid].packetsnotlost = (MAVlist[sysid, compid].packetsnotlost*0.8f); } // extract wp's from stream if (buffer.Length >= 5) { getWPsfromstream(ref message, sysid, compid); } // if its a gcs packet - dont process further if (buffer.Length >= 5 && (sysid == 255 || sysid == 253) && logreadmode) // gcs packet { return message; } // create a state for any sysid/compid if (!MAVlist.Contains(sysid, compid)) { // create an item - hidden MAVlist.AddHiddenList(sysid, compid); } try { if ((message.header == 'U' || message.header == 0xfe || message.header == 0xfd) && buffer.Length >= message.payloadlength) { // check if we lost pacakets based on seqno int expectedPacketSeqNo = ((MAVlist[sysid, compid].recvpacketcount + 1)%0x100); { // the seconds part is to work around a 3dr radio bug sending dup seqno's if (packetSeqNo != expectedPacketSeqNo && packetSeqNo != MAVlist[sysid, compid].recvpacketcount) { MAVlist[sysid, compid].synclost++; // actualy sync loss's int numLost = 0; if (packetSeqNo < ((MAVlist[sysid, compid].recvpacketcount + 1))) // recvpacketcount = 255 then 10 < 256 = true if was % 0x100 this would fail { numLost = 0x100 - expectedPacketSeqNo + packetSeqNo; } else { numLost = packetSeqNo - expectedPacketSeqNo; } MAVlist[sysid, compid].packetslost += numLost; WhenPacketLost.OnNext(numLost); log.InfoFormat("mav {2}-{4} seqno {0} exp {3} pkts lost {1}", packetSeqNo, numLost, sysid, expectedPacketSeqNo,compid); } MAVlist[sysid, compid].packetsnotlost++; //Console.WriteLine("{0} {1}", sysid, packetSeqNo); MAVlist[sysid, compid].recvpacketcount = packetSeqNo; } WhenPacketReceived.OnNext(1); // packet stats per mav if (double.IsInfinity(MAVlist[sysid, compid].packetspersecond[msgid])) MAVlist[sysid, compid].packetspersecond[msgid] = 0; MAVlist[sysid, compid].packetspersecond[msgid] = (((1000 / ((DateTime.Now - MAVlist[sysid, compid] .packetspersecondbuild[msgid]) .TotalMilliseconds) + MAVlist[sysid, compid].packetspersecond[ msgid]) / 2)); MAVlist[sysid, compid].packetspersecondbuild[msgid] = DateTime.Now; //Console.WriteLine("Packet {0}",temp[5]); // store packet history lock (objlock) { MAVlist[sysid, compid].packets[msgid] = message; // 3dr radio status packet are injected into the current mav if (msgid == (byte)MAVLink.MAVLINK_MSG_ID.RADIO_STATUS || msgid == (byte)MAVLink.MAVLINK_MSG_ID.RADIO) { MAVlist[sysidcurrent, compidcurrent].packets[msgid] = message; } // adsb packets are forwarded and can be from any sysid/compid if (msgid == (byte)MAVLink.MAVLINK_MSG_ID.ADSB_VEHICLE) { var adsb = message.ToStructure<MAVLink.mavlink_adsb_vehicle_t>(); MainV2.instance.adsbPlanes[adsb.ICAO_address.ToString("X5")] = new MissionPlanner.Utilities.adsb.PointLatLngAltHdg(adsb.lat / 1e7, adsb.lon / 1e7, adsb.altitude / 1000, adsb.heading * 0.01f, adsb.ICAO_address.ToString("X5"), DateTime.Now); } } // set seens sysid's based on hb packet - this will hide 3dr radio packets if (msgid == (byte)MAVLink.MAVLINK_MSG_ID.HEARTBEAT) { mavlink_heartbeat_t hb = message.ToStructure<mavlink_heartbeat_t>(); // not a gcs if (hb.type != (byte) MAV_TYPE.GCS) { // add a seen sysid if (!MAVlist.Contains(sysid, compid, false)) { // ensure its set from connect or log playback MAVlist.Create(sysid, compid); MAVlist[sysid, compid].aptype = (MAV_TYPE) hb.type; MAVlist[sysid, compid].apname = (MAV_AUTOPILOT) hb.autopilot; setAPType(sysid, compid); } // attach to the only remote device. / default to first device seen if (MAVlist.Count == 1) { sysidcurrent = sysid; compidcurrent = compid; } } } // only process for active mav if (sysidcurrent == sysid && compidcurrent == compid) PacketReceived(message); if (debugmavlink) DebugPacket(message); if (msgid == (byte)MAVLink.MAVLINK_MSG_ID.STATUSTEXT) // status text { var msg = message.ToStructure<MAVLink.mavlink_statustext_t>(); byte sev = msg.severity; string logdata = Encoding.ASCII.GetString(msg.text); int ind = logdata.IndexOf('\0'); if (ind != -1) logdata = logdata.Substring(0, ind); log.Info(DateTime.Now + " " + sev + " " + logdata); MAVlist[sysid, compid].cs.messages.Add(logdata); bool printit = false; // the change of severity and the autopilot version where introduced at the same time, so any version non 0 can be used // copter 3.4+ // plane 3.4+ if (MAVlist[sysid, compid].cs.version.Major > 0 || MAVlist[sysid, compid].cs.version.Minor >= 4) { if (sev <= (byte) MAV_SEVERITY.WARNING) { printit = true; } } else { if (sev >= 3) { printit = true; } } if (logdata.StartsWith("Tuning:")) printit = true; if (printit) { MAVlist[sysid, compid].cs.messageHigh = logdata; MAVlist[sysid, compid].cs.messageHighTime = DateTime.Now; if (MainV2.speechEngine != null && MainV2.speechEngine.IsReady && Settings.Instance["speechenable"] != null && Settings.Instance["speechenable"].ToString() == "True") { MainV2.speechEngine.SpeakAsync(logdata); } } } if (lastparamset != DateTime.MinValue && lastparamset.AddSeconds(10) < DateTime.Now) { lastparamset = DateTime.MinValue; if (BaseStream.IsOpen) { doCommand(MAV_CMD.PREFLIGHT_STORAGE, 0, 0, 0, 0, 0, 0, 0); } } getWPsfromstream(ref message, sysid, compid); try { if (logfile != null && logfile.CanWrite && !logreadmode) { lock (logfile) { byte[] datearray = BitConverter.GetBytes( (UInt64) ((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds*1000)); Array.Reverse(datearray); logfile.Write(datearray, 0, datearray.Length); logfile.Write(buffer, 0, buffer.Length); if (msgid == 0) { // flush on heartbeat - 1 seconds logfile.Flush(); rawlogfile.Flush(); } } } } catch (Exception ex) { log.Error(ex); } try { // full rw from mirror stream if (MirrorStream != null && MirrorStream.IsOpen) { MirrorStream.Write(buffer, 0, buffer.Length); while (MirrorStream.BytesToRead > 0) { byte[] buf = new byte[1024]; int len = MirrorStream.Read(buf, 0, buf.Length); if (MirrorStreamWrite) BaseStream.Write(buf, 0, len); } } } catch { } } } catch (Exception ex) { log.Error(ex); } // update last valid packet receive time MAVlist[sysid, compid].lastvalidpacket = DateTime.Now; return new MAVLinkMessage(buffer); }
public static byte[] GetBytes(byte[] password, byte[] salt, int iterations, int howManyBytes) { // round up uint cBlocks = (uint)((howManyBytes+ HASH_SIZE_IN_BYTES-1)/HASH_SIZE_IN_BYTES); // seed for the pseudo-random fcn: salt + block index byte[] saltAndIndex = new byte[salt.Length + 4]; Array.Copy(salt, 0, saltAndIndex, 0, salt.Length); byte[] output = new byte[cBlocks*HASH_SIZE_IN_BYTES]; int outputOffset = 0; SHA256Managed innerHash = new SHA256Managed(); SHA256Managed outerHash = new SHA256Managed(); // HMAC says the key must be hashed or padded with zeros // so it fits into a single block of the hash in use if (password.Length > BLOCK_SIZE_IN_BYTES) { password = innerHash.ComputeHash(password); } byte[] key = new byte[BLOCK_SIZE_IN_BYTES]; Array.Copy(password, 0, key, 0, password.Length); byte[] InnerKey = new byte[BLOCK_SIZE_IN_BYTES]; byte[] OuterKey = new byte[BLOCK_SIZE_IN_BYTES]; for (int i = 0; i < BLOCK_SIZE_IN_BYTES; ++i) { InnerKey[i] = (byte)(key[i] ^ IPAD); OuterKey[i] = (byte)(key[i] ^ OPAD); } // for each block of desired output for (int iBlock = 0; iBlock < cBlocks; ++iBlock) { // seed HMAC with salt & block index _incrementBigEndianIndex(saltAndIndex, salt.Length); byte[] U = saltAndIndex; for (int i = 0; i < iterations; ++i) { // simple implementation of HMAC-SHA-256 innerHash.Initialize(); innerHash.TransformBlock(InnerKey, 0, BLOCK_SIZE_IN_BYTES, InnerKey, 0); innerHash.TransformFinalBlock(U, 0, U.Length); byte[] temp = innerHash.Hash; outerHash.Initialize(); outerHash.TransformBlock(OuterKey, 0, BLOCK_SIZE_IN_BYTES, OuterKey, 0); outerHash.TransformFinalBlock(temp, 0, temp.Length); U = outerHash.Hash; // U = result of HMAC // xor result into output buffer _xorByteArray(U, 0, HASH_SIZE_IN_BYTES, output, outputOffset); } outputOffset += HASH_SIZE_IN_BYTES; } byte[] result = new byte[howManyBytes]; Array.Copy(output, 0, result, 0, howManyBytes); return result; }
/// <summary> /// Generates the play ready content key. /// </summary> /// <param name="keySeed">The key seed.</param> /// <param name="keyId">The key id.</param> /// <returns>The content key.</returns> public static byte[] GeneratePlayReadyContentKey(byte[] keySeed, Guid keyId) { if (keySeed == null) { throw new ArgumentNullException("keySeed"); } byte[] contentKey = new byte[EncryptionUtils.KeySizeInBytesForAes128]; // Truncate the key seed to 30 bytes. byte[] truncatedKeySeed = new byte[30]; if (keySeed.Length < truncatedKeySeed.Length) { throw new ArgumentOutOfRangeException("keySeed", "KeySeed must be at least 30 bytes in length"); } Array.Copy(keySeed, truncatedKeySeed, truncatedKeySeed.Length); // Get the keyId as a byte array. byte[] keyIdAsBytes = keyId.ToByteArray(); using (SHA256Managed sha_A = new SHA256Managed()) using (SHA256Managed sha_B = new SHA256Managed()) using (SHA256Managed sha_C = new SHA256Managed()) { // Create sha_A_Output buffer. It is the SHA of the truncatedKeySeed and the keyIdAsBytes. sha_A.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_A.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length); byte[] sha_A_Output = sha_A.Hash; // Create sha_B_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes, and // the truncatedKeySeed again. sha_B.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_B.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0); sha_B.TransformFinalBlock(truncatedKeySeed, 0, truncatedKeySeed.Length); byte[] sha_B_Output = sha_B.Hash; // Create sha_C_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes, // the truncatedKeySeed again, and the keyIdAsBytes again. sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_C.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0); sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_C.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length); byte[] sha_C_Output = sha_C.Hash; for (int i = 0; i < EncryptionUtils.KeySizeInBytesForAes128; i++) { contentKey[i] = Convert.ToByte(sha_A_Output[i] ^ sha_A_Output[i + EncryptionUtils.KeySizeInBytesForAes128] ^ sha_B_Output[i] ^ sha_B_Output[i + EncryptionUtils.KeySizeInBytesForAes128] ^ sha_C_Output[i] ^ sha_C_Output[i + EncryptionUtils.KeySizeInBytesForAes128]); } } return contentKey; }
static public byte[] GeneratePlayReadyContentKey(byte[] keySeed, Guid keyId) { const int DRM_AES_KEYSIZE_128 = 16; byte[] contentKey = new byte[DRM_AES_KEYSIZE_128]; // // Truncate the key seed to 30 bytes, key seed must be at least 30 bytes long. // byte[] truncatedKeySeed = new byte[30]; Array.Copy(keySeed, truncatedKeySeed, truncatedKeySeed.Length); // // Get the keyId as a byte array // byte[] keyIdAsBytes = keyId.ToByteArray(); // // Create sha_A_Output buffer. It is the SHA of the truncatedKeySeed and the keyIdAsBytes // SHA256Managed sha_A = new SHA256Managed(); sha_A.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_A.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length); byte[] sha_A_Output = sha_A.Hash; // // Create sha_B_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes, and // the truncatedKeySeed again. // SHA256Managed sha_B = new SHA256Managed(); sha_B.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_B.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0); sha_B.TransformFinalBlock(truncatedKeySeed, 0, truncatedKeySeed.Length); byte[] sha_B_Output = sha_B.Hash; // // Create sha_C_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes, // the truncatedKeySeed again, and the keyIdAsBytes again. // SHA256Managed sha_C = new SHA256Managed(); sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_C.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0); sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0); sha_C.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length); byte[] sha_C_Output = sha_C.Hash; for (int i = 0; i < DRM_AES_KEYSIZE_128; i++) { contentKey[i] = Convert.ToByte(sha_A_Output[i] ^ sha_A_Output[i + DRM_AES_KEYSIZE_128] ^ sha_B_Output[i] ^ sha_B_Output[i + DRM_AES_KEYSIZE_128] ^ sha_C_Output[i] ^ sha_C_Output[i + DRM_AES_KEYSIZE_128]); } return contentKey; }