json_to_nfc
.py
keyboard_arrow_up
School
University of Washington *
*We aren’t endorsed by this school
Course
548
Subject
Computer Science
Date
Feb 20, 2024
Type
py
Pages
1
Uploaded by PresidentRam6103
# Script to convert proxmark JSON output to Flipper Mifare Classic NFC File Format
import json
import argparse
def add_spaces_to_hex(in_str):
# converts something like "AB00BA" to "AB 00 BA"
out_str = ""
for i in range(0, len(in_str), 2):
out_str += in_str[i:i+2] + " "
return out_str.strip()
def guess_mifare_size_by_sak(SAK):
if SAK == "18":
return "4K"
elif SAK == "08":
return "1K"
else:
return "idk"
parser = argparse.ArgumentParser(description='Convert proxmark JSON output to Flipper Mifare classic NFC File Format')
parser.add_argument('-i', '--input', help='Input file', required=True)
parser.add_argument('-o', '--output', help='Output file', required=True)
parser.add_argument('-v', '--verbose', help='Verbose output', action='store_true')
parser.add_argument('-k', '--keys-only', help='Only output keys', action='store_true')
args = parser.parse_args()
with open(args.input, 'r') as f:
data = json.load(f)
if args.keys_only:
# just output the keys to a file
with open(args.output, 'w') as f:
for sector in data['SectorKeys']:
f.write(data)
else:
with open(args.output, 'w') as f:
f.write('Filetype: Flipper NFC device\n')
f.write('Version: 2\n')
f.write('# Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card\n')
f.write('Device type: Mifare Classic\n')
f.write('# UID, ATQA and SAK are common for all formats\n')
f.write('UID: ' + add_spaces_to_hex(data['Card']['UID']) + '\n')
f.write('ATQA: ' + add_spaces_to_hex(data['Card']['ATQA']) + '\n')
f.write('SAK: ' + add_spaces_to_hex(data['Card']['SAK']) + '\n')
f.write('# Mifare Classic specific data\n')
if guess_mifare_size_by_sak(data['Card']['SAK']) == "4K":
f.write('Mifare Classic type: 4K\n')
elif guess_mifare_size_by_sak(data['Card']['SAK']) == "1K":
f.write('Mifare Classic type: 1K\n')
f.write('# Mifare Classic blocks\n')
for block in range(0, len(data['blocks'])):
f.write('Block ' + str(block) + ': ' + add_spaces_to_hex(data['blocks']
[str(block)]) + '\n')
Discover more documents: Sign up today!
Unlock a world of knowledge! Explore tailored content for a richer learning experience. Here's what you'll get:
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
Related Questions
please code in python
Find the expanded DNA strand: this is the opposite of the compression technique described in 3. So, it basically undoes the compressing. For example, CAGGTTT is the expanded form of CA2G3T, TATTGC is the expanded form of TA2TGC, and TAGC is the expanded form of TAGC.
arrow_forward
One method that can be used to compress text data is run length encoding (RLE). When RLE is used the compressed data can be represented as a set of character/frequency pairs. When the same character appears in consecutive locations in the original text it is replaced in the compressed text by a single instance of the character followed by a number indicating the number of consecutive instances of that character. Single instances of a character are represented by the character followed by the number 1.
Figure 9 and Figure 10 show examples of how text would be compressed using this method.
Figure 9
Original text: AAARRRRGGGHH
Compressed text: A 3 R 4 G 3 H 2
Figure 10
Original text: CUTLASSES
Compressed text: C 1 U 1 T 1 L 1 A 1 S 2 E 1 S 1
What you need to do
Task 1
Write a Python program that will perform the compression process described above. The program should display a suitable prompt asking the user to input the text to compress and then output the compressed text.
Task 2
Test…
arrow_forward
Create an RLE class that uses fixed-length encoding to reduce ASCII bytestreams with a limited number of characters, including the code as part of the compressed bitstream. Add code to compress() to generate a string alpha containing all of the unique letters in the message and use it to generate an Alphabet for use in compress(), prepend alpha (8-bit encoding plus its length) to the compressed bitstream, and then add code to expand() to read the alphabet before expansion.
arrow_forward
Create an RLE class that employs fixed-length encoding to compress ASCII bytestreams with a limited number of characters, including the code as part of the encoded bitstream. Add code to compress() to generate a string alpha containing all of the different characters in the message and use it to generate an Alphabet for use in compress(), prepend alpha (8-bit encoding plus its length) to the compressed bitstream, and then add code to expand() to read the alphabet before expansion.
arrow_forward
Create an RLE class that uses fixed-length encoding to compress ASCII bytestreams with a defined number of characters, including the code in the encoded bitstream. Add code to compress() to generate a string alpha containing all of the message's characters and use it to generate an Alphabet for use in compress(), prepend alpha (8-bit encoding plus its length) to the compressed bitstream, and then add code to expand() to read the alphabet before expansion.
arrow_forward
Please don't copy The following question is on the LZ77 lossless data compression algorithm:
arrow_forward
MATLAB: Create function files that will:generate sequence y(n) = x1(n) + x2(n)[y,n] = sigadd(x1,n1,x2,n2)
arrow_forward
JAVA
File read write and string manipulation
data1.txt(down below)
4,5-t 2,4-d 20-p7int 2D 2nd 2 1080 &c 10-p7int 10th 11-p7int 12-p7int 16-p7int 18-p7int 1st 2,4,5-t 2,4-d 20-p7int 2D 2nd 30-30 3D 3-D 3M 3rd 48-p7int 4-D 4GL 4H 4th 5-p7int 5-T 5th 6-p7int 6th 7-p7int 7th 8-p7int 8th 9-p7int 9th @ @' @- @&M @&P @. @.@.@. @.B. @.B.@. @.C. @.D. @.D.C. @.F. @.F.@.M. @.G. @.H. @.I. @.I.@. @.I.D. @.L. @.L.P. @.M. @.M.@. @.M.D.G. @.N. @.p. @.r. @.R.C.S. @.U. @.U.C. @.V. @.w. @.W.O.L. @/C @/F j54rs54y54d J54rs54yit54 j54rs54yit54s J54rs54ym@n j54rs54ys j54rs54y's J54rs54yvill54 j54rt J54rubb@@l J54rubb@l J54rus@l54m J54rus@l54mit54 j54rvi@ j54rvin j54rvin@ j54rvin54 J54rvis J54rk J54S J54sh J54sh54r J54smin54 j54sp54r J54sp54rs54n J54ss J54ss@ J54ss@b54ll j54ss@k5454d J54ss@lin J54ss@lyn j54ss@my j54ss@mi54s J54ss@myn J54ss@min54 j54ss@nt J54ss54 J54ss54@n j54ss54d J54ss5454 J54ss54y J54ss54lyn J54ss54lt7n J54ss54n j54ss54s J54ssi J54ssy J54ssic@ J54ssi54 kikkl54 kikkl54d kikkl54s…
arrow_forward
implement greatestBitPos function Compute a mask marking the most significant 1 bit.
you are only allowed to use the following eight operators: ! ~ & ^ | + << >>
“Max ops” field gives the maximum number of operators you are allowed to use to implement each function
/* * greatestBitPos - return a mask that marks the position of the* most significant 1 bit. If x == 0, return 0* Example: greatestBitPos(96) = 0x40* Legal ops: ! ~ & ^ | + << >>* Max ops: 70* Rating: 4 */int greatestBitPos(int x) {return 2;}
arrow_forward
/* * copyLSB - set all bits of result to least significant bit of x * Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000 * Legal ops: ! ~ & ^ | + << >> * Max ops: 5 * Rating: 2 */int copyLSB(int x) { return 2;}
arrow_forward
Write a C++ program that reads two items from a data file, the bit string itself and the parity required, and then adjusts the bit string and then expresses both the original string and the parity adjusted string in hexadecimal form.Sample Run:Enter the bit string and parity (EVEN or ODD): 10110101 EVENOriginal Hex Value: B5Parity Adjusted Hex Value: 16B
arrow_forward
True or false: A dataword (k) and a codeword (n) vary in that the k=n+FCS (Frame Check Sequence).
arrow_forward
Please use python and python file i/o to solve the problem. Create an input file input3_1.txt take input from sample input as shown below, solve the problem and print the output to output3_1.txt file as shown in the question.
arrow_forward
In execution of the following code with the
following bytes contents:
START:
CLC
MOV CX, 0002
MOV SI, 0300
MOV DI, 0302
LOOP:
ADC (SI), AL
INC SI
INC DI
DEC CX
JNZ LOOP
HLT
3CH, (0303H) = 4DH.
MOV AL, (DI)
(0300H) = 1AH, (0301H) = 2BH, (0302H) =
The result will be:
a. (0300H) = 1AH, (0301H) = 2BH, (0302H)
= 66H, (0303H) = 77H
b. (0300H) = 1AH, (0301H) = 2BH, (0302H)
= 3CH, (0303H) = 4DH
C. (0300H) = 1AH, (0301H) = 2BH, (0302H)
= 56H, (0303H) = 87H
d. None of the options given here.
Select one:
arrow_forward
Problem Y:
Implement the reader writer problem using pthreads and semaphores. You
should allow multiple readers to read at the same time and only one single
writer to write to the data set. You are required to use the following:
1. A semaphore rw_muter initialized to 1.
2. A semaphore muter initialized to 1.
3. An integer reader_count initialized to 0.
arrow_forward
actical Quiz (Protected View) - Word
View.
Enable Editing
S= 53 /y*+75/y*+ 97/y* +..
+n* 3/y*
For example, if n 9, then the product would be 53 /y*+75/y*+ 97/y*,
where x and y are variables whose values are taken from the user.
arrow_forward
Write a program in M-File to read 3 x 3 Matrix, then display the diagonal of matrix as
shown below:
The Diagonal of This Matrix
Q3/
arrow_forward
Number Sequence A3
main.c
Test Case 1-input 3, expected output 19 27 35
Test Case 2-input 6, expected output 19 27 35 43 51 59
Test Case 3-input 9, expected output 19 27 35 43 51 59 67 75 83
arrow_forward
sample.txt file :
0.277098834317 , 0.9852789439140.30469825847 , 1.071132744780.335349108089 , 1.046437314030.313771100286 , 1.066080329830.291255984459 , 1.003773163560.294997556075 , 1.005107485690.30551242839 , 1.049082932110.312278701405 , 1.00054161340.229034833336 , 1.07650109960.238560972323 , 1.040408482320.217499589016 , 1.172997657680.316159908608 , 1.168589175430.311929396532 , 1.137994231150.421567449877 , 1.164852887720.305392530731 , 1.072739158510.342611226456 , 0.9880239512480.310465976618 , 1.031075352780.290874789102 , 1.027863857230.365324167651 , 0.9320114710.324532611761 , 0.8346451323330.307651402732 , 1.018307587490.325937725289 , 1.093998546940.323733397397 , 0.9787758456070.31329702072 , 1.063332993070.296978896122 , 1.228464321280.345083122488 , 0.9504863449260.257474591167 , 1.181370847070.30852261837 , 1.18860596160.287400310146 , 1.134833828640.492626799434 , 1.103715219080.36692925721 , 1.028287001470.4290602186 , 1.27998954490.427877860063 ,…
arrow_forward
Given a JSON file, read the data and complete the following:
Open the JSON file and read the contents into a variable (aka memory)
Sort the characters by the dob key
Loop through each character and output the sentence in the following format
Admiral Jonathan Archer was born on October 09, 2112 and first appeared in Enterprise
The sentence in the print() statement should be a single string statement, no commas seperating values
Research how to use the sorted() method to sort your dictionaries by a specific key
work for far:
# Define Main Program
import json
def main():
with open('x:/json_file.json') as file_object:
data = json.load(file_object)
print(data)
pass
# DO NOT MODIFY BELOW
if __name__ == "__main__":
# Call Main Program
main()
data.Json
{ "characters": [ { "name_first": "Jonathan", "name_last": "Archer", "rank": "Admiral", "dob": "21121009", "series": "Star Trek: Enterprise" }, { "name_first": "Michael", "name_last": "Burnham", "rank":…
arrow_forward
Help
arrow_forward
P7
arrow_forward
49
arrow_forward
You started working for a talent agency. Your supervisor gave you a job to rename 50 files saved in a photographer's folder and the filenames start with dsc001.jpg thru dsc050.jpg. The photographer used a list on a printout of the firstnames of the talents in alphabetical order and he said the JPEG files are numbered by the alphabetical order that the talents were called for the photos.You were given a file of all the talents that were in the photoshoot (also 50 names). The names are not in alphabetical order.It is easy to rename files by typing this command as an example: ren dsc001.jpg Adam.jpgManually doing so is prone to mistakes and your supervisor does not want to show the wrong picture in the web site.Because you just finished learning C++ programming, you are confident to write a new program that will do the following:1. Read the names.txt file and save each name in string array.2. Sort the array in alphabetical order. Choose a sorting algorithm that you have learned in…
arrow_forward
You started working for a talent agency. Your supervisor gave you a job to rename 50 files saved in a photographer's folder and the filenames start with dsc001.jpg thru dsc050.jpg. The photographer used a list on a printout of the firstnames of the talents in alphabetical order and he said the JPEG files are numbered by the alphabetical order that the talents were called for the photos.You were given a file of all the talents that were in the photoshoot (also 50 names). The names are not in alphabetical order.It is easy to rename files by typing this command as an example: ren dsc001.jpg Adam.jpgManually doing so is prone to mistakes and your supervisor does not want to show the wrong picture in the web site.Because you just finished learning C++ programming, you are confident to write a new program that will do the following:1. Read the names.txt file and save each name in string array.2. Sort the array in alphabetical order. Choose a sorting algorithm that you have learned in…
arrow_forward
Please use python and python file i/o to solve the problem. Create an input file input1_1.txt as shown below, solve the problem and print the output to output1_1.txt file as shown in the question.
arrow_forward
Code Tracing: Show the output of the following code:
mov qword [f], 61
mov rcx, 5
amazing:
cmp rcx, 3
jl here
add qword [f], 4
jmp there
here:
there:
add qword [f], 6
mov rsi, f
push rcx
call printNow
pop rcx
loop amazing
;prints one character whose ASCII value is equal to f
arrow_forward
Time complexity
A computer runs a program to generate all the strings from a set of characters,then search a dictionary to see if each word generated is in the dictionary. Itthen writes the output to a file at a rate of 1200 words/sec all generated andchecked. How long will it take the computer to generate, check and output all thewords from a string of 5 (distinct) characters? How long if there are repeatedcharacters?
arrow_forward
Type or paste question here
arrow_forward
java help please with the following images.
arrow_forward
To be done using C programming:Two identical files are given with different names to them. But some characters in the content of the second file are corrupted. Find the line number and their position where those corrupted letter exists as well as Total number of corrupted (error) letters.
Examples:
Input:
File1.txt contains
It is fun to code
with C
File1.txt contains
It is fun to code
with C#
Output:
Line Number : 2
Error Position:2
Total Errors:1
Steps
Open two file using File pointer in read only mode.
Fetch data of file in two char variable one by one until end of file.
If variable encounter new line then increment line number and reset position to zero.
If variables are not equal then increment number of error and print error line as well as error index.
arrow_forward
This exercise is to write a Decimal to Hex function using BYTE operations. See the Bitstreams.pdf on Canvas for a Bit/Byte Operation review. You can use a
List, Dictionary or Tuple for your Hex_Map as shown below, but it's not necessary to use one. It is necessary to use Byte operations to convert the decimal to
hex. The bitwise operations are also available as __dunders___.
In question #6, I asked you to write a decimal to hex function:
Write a function to convert a integer to hexidecimal. Do not use the Python hex function (i.e. hexnumber = hex(number)) to convert the number, instead write
your own unique version (i.e. MYHEX: hexnumber = MYHEX(number)). Your function should not use any Python functions like hex, dec, oct, bin or any other
Python functions or modules. Functions, like Python ORD, can be used to convert a string to a integer. The input number range is 0 to 1024.
Most students submitted versions using this algorithm and the primary algorithm calculates list[index] using…
arrow_forward
Convert the following infix expression to postfix and prefix expression.K+L-M*N+(O^P)*W/U/V*T+Q
arrow_forward
Please use python and python file i/o to solve the problem. Create an input file input1_1.txt take input from sample input as shown below, solve the problem and print the output to output1_1.txt file as shown in the question.
arrow_forward
SEE MORE QUESTIONS
Recommended textbooks for you
Database System Concepts
Computer Science
ISBN:9780078022159
Author:Abraham Silberschatz Professor, Henry F. Korth, S. Sudarshan
Publisher:McGraw-Hill Education
Starting Out with Python (4th Edition)
Computer Science
ISBN:9780134444321
Author:Tony Gaddis
Publisher:PEARSON
Digital Fundamentals (11th Edition)
Computer Science
ISBN:9780132737968
Author:Thomas L. Floyd
Publisher:PEARSON
C How to Program (8th Edition)
Computer Science
ISBN:9780133976892
Author:Paul J. Deitel, Harvey Deitel
Publisher:PEARSON
Database Systems: Design, Implementation, & Manag...
Computer Science
ISBN:9781337627900
Author:Carlos Coronel, Steven Morris
Publisher:Cengage Learning
Programmable Logic Controllers
Computer Science
ISBN:9780073373843
Author:Frank D. Petruzella
Publisher:McGraw-Hill Education
Related Questions
- please code in python Find the expanded DNA strand: this is the opposite of the compression technique described in 3. So, it basically undoes the compressing. For example, CAGGTTT is the expanded form of CA2G3T, TATTGC is the expanded form of TA2TGC, and TAGC is the expanded form of TAGC.arrow_forwardOne method that can be used to compress text data is run length encoding (RLE). When RLE is used the compressed data can be represented as a set of character/frequency pairs. When the same character appears in consecutive locations in the original text it is replaced in the compressed text by a single instance of the character followed by a number indicating the number of consecutive instances of that character. Single instances of a character are represented by the character followed by the number 1. Figure 9 and Figure 10 show examples of how text would be compressed using this method. Figure 9 Original text: AAARRRRGGGHH Compressed text: A 3 R 4 G 3 H 2 Figure 10 Original text: CUTLASSES Compressed text: C 1 U 1 T 1 L 1 A 1 S 2 E 1 S 1 What you need to do Task 1 Write a Python program that will perform the compression process described above. The program should display a suitable prompt asking the user to input the text to compress and then output the compressed text. Task 2 Test…arrow_forwardCreate an RLE class that uses fixed-length encoding to reduce ASCII bytestreams with a limited number of characters, including the code as part of the compressed bitstream. Add code to compress() to generate a string alpha containing all of the unique letters in the message and use it to generate an Alphabet for use in compress(), prepend alpha (8-bit encoding plus its length) to the compressed bitstream, and then add code to expand() to read the alphabet before expansion.arrow_forward
- Create an RLE class that employs fixed-length encoding to compress ASCII bytestreams with a limited number of characters, including the code as part of the encoded bitstream. Add code to compress() to generate a string alpha containing all of the different characters in the message and use it to generate an Alphabet for use in compress(), prepend alpha (8-bit encoding plus its length) to the compressed bitstream, and then add code to expand() to read the alphabet before expansion.arrow_forwardCreate an RLE class that uses fixed-length encoding to compress ASCII bytestreams with a defined number of characters, including the code in the encoded bitstream. Add code to compress() to generate a string alpha containing all of the message's characters and use it to generate an Alphabet for use in compress(), prepend alpha (8-bit encoding plus its length) to the compressed bitstream, and then add code to expand() to read the alphabet before expansion.arrow_forwardPlease don't copy The following question is on the LZ77 lossless data compression algorithm:arrow_forward
- MATLAB: Create function files that will:generate sequence y(n) = x1(n) + x2(n)[y,n] = sigadd(x1,n1,x2,n2)arrow_forwardJAVA File read write and string manipulation data1.txt(down below) 4,5-t 2,4-d 20-p7int 2D 2nd 2 1080 &c 10-p7int 10th 11-p7int 12-p7int 16-p7int 18-p7int 1st 2,4,5-t 2,4-d 20-p7int 2D 2nd 30-30 3D 3-D 3M 3rd 48-p7int 4-D 4GL 4H 4th 5-p7int 5-T 5th 6-p7int 6th 7-p7int 7th 8-p7int 8th 9-p7int 9th @ @' @- @&M @&P @. @.@.@. @.B. @.B.@. @.C. @.D. @.D.C. @.F. @.F.@.M. @.G. @.H. @.I. @.I.@. @.I.D. @.L. @.L.P. @.M. @.M.@. @.M.D.G. @.N. @.p. @.r. @.R.C.S. @.U. @.U.C. @.V. @.w. @.W.O.L. @/C @/F j54rs54y54d J54rs54yit54 j54rs54yit54s J54rs54ym@n j54rs54ys j54rs54y's J54rs54yvill54 j54rt J54rubb@@l J54rubb@l J54rus@l54m J54rus@l54mit54 j54rvi@ j54rvin j54rvin@ j54rvin54 J54rvis J54rk J54S J54sh J54sh54r J54smin54 j54sp54r J54sp54rs54n J54ss J54ss@ J54ss@b54ll j54ss@k5454d J54ss@lin J54ss@lyn j54ss@my j54ss@mi54s J54ss@myn J54ss@min54 j54ss@nt J54ss54 J54ss54@n j54ss54d J54ss5454 J54ss54y J54ss54lyn J54ss54lt7n J54ss54n j54ss54s J54ssi J54ssy J54ssic@ J54ssi54 kikkl54 kikkl54d kikkl54s…arrow_forwardimplement greatestBitPos function Compute a mask marking the most significant 1 bit. you are only allowed to use the following eight operators: ! ~ & ^ | + << >> “Max ops” field gives the maximum number of operators you are allowed to use to implement each function /* * greatestBitPos - return a mask that marks the position of the* most significant 1 bit. If x == 0, return 0* Example: greatestBitPos(96) = 0x40* Legal ops: ! ~ & ^ | + << >>* Max ops: 70* Rating: 4 */int greatestBitPos(int x) {return 2;}arrow_forward
- /* * copyLSB - set all bits of result to least significant bit of x * Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000 * Legal ops: ! ~ & ^ | + << >> * Max ops: 5 * Rating: 2 */int copyLSB(int x) { return 2;}arrow_forwardWrite a C++ program that reads two items from a data file, the bit string itself and the parity required, and then adjusts the bit string and then expresses both the original string and the parity adjusted string in hexadecimal form.Sample Run:Enter the bit string and parity (EVEN or ODD): 10110101 EVENOriginal Hex Value: B5Parity Adjusted Hex Value: 16Barrow_forwardTrue or false: A dataword (k) and a codeword (n) vary in that the k=n+FCS (Frame Check Sequence).arrow_forward
arrow_back_ios
SEE MORE QUESTIONS
arrow_forward_ios
Recommended textbooks for you
- Database System ConceptsComputer ScienceISBN:9780078022159Author:Abraham Silberschatz Professor, Henry F. Korth, S. SudarshanPublisher:McGraw-Hill EducationStarting Out with Python (4th Edition)Computer ScienceISBN:9780134444321Author:Tony GaddisPublisher:PEARSONDigital Fundamentals (11th Edition)Computer ScienceISBN:9780132737968Author:Thomas L. FloydPublisher:PEARSON
- C How to Program (8th Edition)Computer ScienceISBN:9780133976892Author:Paul J. Deitel, Harvey DeitelPublisher:PEARSONDatabase Systems: Design, Implementation, & Manag...Computer ScienceISBN:9781337627900Author:Carlos Coronel, Steven MorrisPublisher:Cengage LearningProgrammable Logic ControllersComputer ScienceISBN:9780073373843Author:Frank D. PetruzellaPublisher:McGraw-Hill Education
Database System Concepts
Computer Science
ISBN:9780078022159
Author:Abraham Silberschatz Professor, Henry F. Korth, S. Sudarshan
Publisher:McGraw-Hill Education
Starting Out with Python (4th Edition)
Computer Science
ISBN:9780134444321
Author:Tony Gaddis
Publisher:PEARSON
Digital Fundamentals (11th Edition)
Computer Science
ISBN:9780132737968
Author:Thomas L. Floyd
Publisher:PEARSON
C How to Program (8th Edition)
Computer Science
ISBN:9780133976892
Author:Paul J. Deitel, Harvey Deitel
Publisher:PEARSON
Database Systems: Design, Implementation, & Manag...
Computer Science
ISBN:9781337627900
Author:Carlos Coronel, Steven Morris
Publisher:Cengage Learning
Programmable Logic Controllers
Computer Science
ISBN:9780073373843
Author:Frank D. Petruzella
Publisher:McGraw-Hill Education