Could not parse base64 DER-encoded ASN.1 public key from iOS in Golang - ios

i have a projects in Golang with RSA enryption, so now, i have a Base64 public key format which used for encrypt a message,
i used this code:
publicKeyBase64 = "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
publicKeyBinary, err := base64.StdEncoding.DecodeString(publicKeyBase64)
publicKeyInterface, err := x509.ParsePKIXPublicKey(publicKeyBinary)
if err != nil {
fmt.Println("Could not parse DER encoded public key (encryption key)")
return "","",err
}
publicKey, isRSAPublicKey := publicKeyInterface.(*rsa.PublicKey)
if !isRSAPublicKey {
fmt.Println("Public key parsed is not an RSA public key")
return "","",err
}
encryptedMessage, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, "message")
When i run this code, i got this error:
Could not parse DER encoded public key (encryption key)
asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:129 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} AlgorithmIdentifier #3
The error points to publicKeyInterface, it failed to parse from Base64 decoded format to public Key, What's the problem with my code ?
=======updated=====
my publicKeyBase64 is retrieved from my models with Binary Data type
When i store it in my mongoDB from my Rails API, i receive public_key params as Base64 format, but i decode it to binary and then i stored it with this code
def create
params = device_params
public_key = Base64.decode64 device_params[:public_key]
#device_params[:public_key] value is "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
params[:public_key] = BSON::Binary.new(public_key, :generic)
device = Device.find_or_create_by(id: device_params[:id])
render_success device.update_attributes(params), device
end
When i use rails code to convert my Base64 public key string using this code, it succeeded:
rsa_public_key = OpenSSL::PKey::RSA.new(Base64.decode64(public_key))
in my iOS app, i use https://github.com/DigitalLeaves/AsymmetricCrypto
to generate a public Key using this code:
AsymmetricCryptoManager.sharedInstance.createSecureKeyPair({ (success, error) -> Void in
if success {
print("RSA-1024 keypair successfully generated.")
let publicKey = AsymmetricCryptoManager.sharedInstance.getPublicKeyData()?.base64EncodedString()
let url = ENV.BASE_URL + "devices"
let headers = ["Authentication-Token": CurrentUser.getCurrentUser().token] as! HTTPHeaders
let params = ["device[user_id]": CurrentUser.getCurrentUser().id!, "device[id]": instanceID,"device[token]": fcmToken, "device[os]": "ios", "device[public_key]": publicKey!]
Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding.default, headers: headers)
} else { print("An error happened while generating a keypair: \(error)") }
})

We can dump the ASN.1 contents to see what they look like:
$ echo "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE=" | \
base64 -d | \
dumpasn1 -
0 137: SEQUENCE {
3 129: INTEGER
: 00 92 58 5E 00 5E 9B 5B 1C 2C A3 C4 8F 02 AB 5B
: CF 9C 8B 70 7F 60 D3 77 69 8D 83 27 79 5C E5 ED
: B0 35 CD 12 98 58 A4 0E 9A 30 D5 37 58 70 A9 76
: C1 DA D7 5F BB 0C 46 CC A3 4E 4D 79 20 40 8C 7B
: 3C 87 CD A2 46 43 D4 E2 9E 79 10 8B 12 7E 62 79
: 4D 74 B0 B4 E1 33 56 3A 0D 77 A6 5C 9A 84 85 C1
: 7E 8A D8 02 36 25 DB 05 48 03 C6 26 6B 66 C4 40
: 58 66 00 59 04 5F 50 3F 43 57 48 2B 2E 84 7D 0F
: B1
135 3: INTEGER 65537
: }
0 warnings, 0 errors.
A well-formatted ASN.1 public key should include the algorithm as well. We should have a line similar to:
5 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
The AsymmetricCryptoManager.getPublicKeyData() returns a very barebones ASN.1 key, without any algorithm information. This makes Go very unhappy as it has no way of knowing what kind of key it is. See more about correctly exporting the key here.
If you can change the iOS code, you should instead use CryptoExportImportManager and use one of exportPublicKeyToPEM or exportPublicKeyToDER. These take the output of getPublicKeyData and generate output usable by other tools. You can find an example of how to use them in the CryptoExportImportManager example.
If you cannot change the key export code, you can instead parse it directly in Go. This assumes that you know for sure that it is a RSA public key:
func main() {
publicKeyBase64 := "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
// Base64 decode.
publicKeyBinary, err := base64.StdEncoding.DecodeString(publicKeyBase64)
if err != nil {
panic(err)
}
// rsa.PublicKey is a big.Int (N: modulus) and an integer (E: exponent).
var pubKey rsa.PublicKey
if rest, err := asn1.Unmarshal(publicKeyBinary, &pubKey); err != nil {
panic(err)
} else if len(rest) != 0 {
panic("rest is not nil")
}
fmt.Printf("key: %+v\n", pubKey)
}
This prints out:
key:
{N:+102767083290202280873554060983826675083148443795791447833515664566475334389364583758312108980110921996262487865832851258326049062353432991986398760705560379825908169063986770245967781444794847106351934016144540466696422397564949226710181429429140226472206572796987719088983654589217713611861345869296293449649
E:65537}
You can now use your public key in package rsa functions.

Related

PEM-encoded Elliptic Curve public key conversion iOS

In an iOS application, I receive a PEM-encoded Elliptic curve public key.
I would like to create a SecKey object from it.
This question has been very useful to get RSA key parsing to work.
But I struggle adapting it to work with an EC key.
Example working with an RSA key
var secKeyCreateError : Unmanaged<CFError>?
guard
let stringPublicKey = Data(
base64Encoded: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhT0OXGhPWpbrZBTIScIFQVooi/Qo/NyTYRnrIyZ42nksKCBeSOBu+FPOHCI5U4RUSc2cUOe83dyuKmboU2Kdc1dTq9HDAau3dhpE7VLzZKzMHay+8XW5V6kQJ2oOIGKJphsjJLDM5KxCr5etHEHE5rfrPIBZA0sgcvyT0TsavOAhr55Eu4U2fu8SefxM4CWobXKANiWbmSzzYbo2EIZrfhhe2RncwnH5kr0PMk6Q+kEcuRt58VyYoDAa7vRQvY+KDwxE81CCkIjKpJ55f4uN0/VDclXzFjK8FeOgIiH3n8KD6xqtkvmFc+M8tEJYlzdHWIRN7VoNqbn4IoevnziYhQIDAQAB"
),
let peerPublicKey = SecKeyCreateWithData(
stringPublicKey as CFData,
[
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
] as CFDictionary,
&secKeyCreateError
)
else {
NSLog("Failed to create SecKey : %#", secKeyCreateError!.takeRetainedValue().localizedDescription)
return
}
NSLog("SecKey successfully created")
Example failing with an EC key
var secKeyCreateError : Unmanaged<CFError>?
guard
let stringPublicKey = Data(
base64Encoded: "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhYvCTeKdth6ffyCKReeO7cJSfN94BfieZ/9zkE6sDFz/ZifyMkgeg7mq8XB4UYn7aSEcsnqFNswROLnU4NqVFbmGDi5wAI0jRazdskGFBf+0R/zIPozZgJOSrREMEqi7"
),
let peerPublicKey = SecKeyCreateWithData(
stringPublicKey as CFData,
[
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
] as CFDictionary,
&secKeyCreateError
)
else {
NSLog("Failed to create SecKey : %#", secKeyCreateError!.takeRetainedValue().localizedDescription)
return
}
NSLog("SecKey successfully created")
Execution returns the following logs :
[seckey] SecKeyCreate init(ECPublicKey) failed: -26275
Failed to create SecKey : The operation couldn’t be completed. (OSStatus error -50 - EC public key creation from data failed)
For information, I used https://mkjwk.org/ to generate public keys.
What else did I try
I tried to extract the DER BIT STRING using ASN1Decoder and ASN1Swift without success.
Would you have any idea of what's going on with those EC keys ?
Thanks a lot 🙏
As pointed out by CyonAlexRdx here, a SECG key must be in X9.63 format to be imported using Security Framework.
If your key is in PEM format, you may import it using CryptoKit, then map it to a Security Framework object.
Detailed explainations from eskimo on developer.apple.com forum :
Import SECG Keys with Security Framework
If you’re working with Security framework, use SecKeyCreateWithData to import an SECG key. If you have a secp256r1 public key in X9.63 format:
Apple CryptoKit can import SECG keys in three different ways:
X9.63 raw key bytes
DER encoding
PEM encoding
If you have a secp256r1 public key in X9.63 format, import it with this code:
let u = URL(fileURLWithPath: "p256-public-key.dat")
guard let keyBytes = try? Data(contentsOf: u) else {
… handle error …
}
guard let publicKey = try? P256.Signing.PublicKey(x963Representation: keyBytes) else {
… handle error …
}
print(publicKey)
// prints:
// PublicKey(impl: CryptoKit.CoreCryptoNISTCurvePublicKeyImpl<CryptoKit.P256.CurveDetails>(keyBytes: […]]))
Note I’m using secp256r1 as an example. The code in this section will work for the other SECG key types, secp384r1 and secp521r1.
If you have a secp256r1 private key in X9.63 format import it with this code:
let u = URL(fileURLWithPath: "p256-private-key.dat")
guard let keyBytes = try? Data(contentsOf: u) else {
… handle error …
}
guard let privateKey = try? P256.Signing.PrivateKey(x963Representation: keyBytes) else {
… handle error …
}
print(privateKey)
// prints:
// PrivateKey(impl: CryptoKit.CoreCryptoNISTCurvePrivateKeyImpl<CryptoKit.P256.CurveDetails>(key: CryptoKit.SecureBytes(backing: CryptoKit.SecureBytes.Backing)))
CryptoKit can also import a DER-encoded SECG key. For example, it can import the following using the init(derRepresentation:) initialiser:
% xxd -p public-key-p256.der
3059301306072a8648ce3d020106082a8648ce3d030107034200042c21f3
7049d4464afbf01813c51a4e1ef7a8101d2aa12b6a889635bc7c37e9011b
fdd54006fdebdaef0d86a6d662561347982c95276013d1c1cd2d7865aff0
23
%
% dumpasn1 -p -a public-key-p256.der
SEQUENCE {
SEQUENCE {
OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
}
BIT STRING
04 2C 21 F3 70 49 D4 46 4A FB F0 18 13 C5 1A 4E
1E F7 A8 10 1D 2A A1 2B 6A 88 96 35 BC 7C 37 E9
01 1B FD D5 40 06 FD EB DA EF 0D 86 A6 D6 62 56
13 47 98 2C 95 27 60 13 D1 C1 CD 2D 78 65 AF F0
23
}
%
% xxd -p private-key-p256.der
308187020100301306072a8648ce3d020106082a8648ce3d030107046d30
6b0201010420986a7a91cbb5f4f81636e81aaff0835a771dc66865c407a8
e84469cf6ab8a477a144034200049747e981aab8ea71a255cd9a1562858c
406006f1e418260d31e1a77f6c2b35a9a3132f232db00351d9d8003487d4
ee52847990313daa7c721f88d4bb56da91c7
%
% dumpasn1 -p -a private-key-p256.der
SEQUENCE {
INTEGER 0
SEQUENCE {
OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
}
OCTET STRING, encapsulates {
SEQUENCE {
INTEGER 1
OCTET STRING
98 6A 7A 91 CB B5 F4 F8 16 36 E8 1A AF F0 83 5A
77 1D C6 68 65 C4 07 A8 E8 44 69 CF 6A B8 A4 77
[1] {
BIT STRING
04 97 47 E9 81 AA B8 EA 71 A2 55 CD 9A 15 62 85
8C 40 60 06 F1 E4 18 26 0D 31 E1 A7 7F 6C 2B 35
A9 A3 13 2F 23 2D B0 03 51 D9 D8 00 34 87 D4 EE
52 84 79 90 31 3D AA 7C 72 1F 88 D4 BB 56 DA 91
C7
}
}
}
}
Finally, CryptoKit can import a PEM-encoded SECG. For example, it can import the following using the init(pemRepresentation:) initialiser:
% cat public-key-p256.pem
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELCHzcEnURkr78BgTxRpOHveoEB0q
oStqiJY1vHw36QEb/dVABv3r2u8NhqbWYlYTR5gslSdgE9HBzS14Za/wIw==
-----END PUBLIC KEY-----
% cat private-key-p256.pem
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgmGp6kcu19PgWNuga
r/CDWncdxmhlxAeo6ERpz2q4pHehRANCAASXR+mBqrjqcaJVzZoVYoWMQGAG8eQY
Jg0x4ad/bCs1qaMTLyMtsANR2dgANIfU7lKEeZAxPap8ch+I1LtW2pHH
-----END PRIVATE KEY-----
Mapping SECG Keys between Apple CryptoKit and Security Framework
If you need to map an SECG key from Apple CryptoKit to Security framework, or vice versa, use the X9.63 format.
Imagine that you’re working in Security framework but you need to import a PEM key. SecKeyCreateWithData will not accept an SECG key in PEM format; it requires that the key be in X9.63 format. CryptoKit can import a PEM key but you want to continue using your existing Security framework code. Fortunately there’s a way out of this bind:
Import the PEM key using Apple CryptoKit.
Get the X9.63 representation.
Create the Security framework key from that.
For example, the following routine imports a PEM secp256r1 private key and returns a SecKey object:
func createSecKeyWithPEMSecp256r1Private(_ pem: String) throws -> SecKey {
let privateKeyCK = try P256.Signing.PrivateKey(pemRepresentation: pem)
let x963Data = privateKeyCK.x963Representation
var errorQ: Unmanaged<CFError>? = nil
guard let privateKeySF = SecKeyCreateWithData(x963Data as NSData, [
kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
] as NSDictionary, &errorQ) else {
throw errorQ!.takeRetainedValue()
}
return privateKeySF
}
To go the other way, from Security framework to CryptoKit, call SecKeyCopyExternalRepresentation to get the X9.63 representation of the key and then create a CryptoKit value using the init(x963Representation:) initialiser.

Playing recorded audio results in ACMP4AACBaseDecoder failing

I'm playing around with a really simple audio use case. I'm recording via AVAudioRecorder and playing the recorded audio via AVAudioPlayer. The way I configured it is to set up the AVAudioRecorder once when the view controller is presented and record over the same file whenever record is initiated. Playing will play the url used by the recorder. The first recording and play back work fine. However if I try to record and play again I get the following:
2022-12-30 10:39:09.874066-0800 [40936:5138438] Error deserializing gain control data
2022-12-30 10:39:09.874246-0800 [40936:5138438] Error deserializing right channel stream
2022-12-30 10:39:09.874443-0800 [40936:5138438] Error in deserializing element
2022-12-30 10:39:09.874545-0800 [40936:5138438] Error deserializing packet
2022-12-30 10:39:09.874675-0800 [40936:5138438] [ac] ACMP4AACBaseDecoder.cpp:1438 (0x127850040) Error decoding packet 1: err = -1, packet length: 198
2022-12-30 10:39:09.874781-0800 [40936:5138438] [ac] ACMP4AACBaseDecoder.cpp:1447 '21 4E E5 44 87 E2 FC 62 0A 9B 64 42 80 D5 4E 01 17 D0 9D 47 CF FA E0 91 D2 5C FD 28 8B 3E 04 3A FD 71 F0 43 6D 20 48 52 EB 6C 73 7D 30 98 41 CC 12 F9 27 C3 10 60 4F 67 41 F6 4F 59 F1 A6 45 A4 B4 87 6A 4F 34 9C 26 CF 03 9A 9C 8D 20 14 6E 72 E6 C5 08 A6 BC D7 3B DE 3D 7F 61 1A 23 38 EC 95 1E 71 C8 1A D4 F1 B0 6E ED 9C 53 D3 FD 0E E1 5B AA CD 83 8F D3 0D 40 D7 D1 94 B4 F5 A8 1A 13 4D CE E2 37 69 14 FA E9 01 A2 50 2C AE 9C 75 49 04 06 8B 6F 01 23 20 0D 3E F1 5B 6F 47 D3 F3 F3 8A 06 E9 C5 AB 34 84 28 21 C7 4D DA 47 BE 9E 1A D5 6A B8 74 B2 EA 21 1D 51 0B 2D CE 1C 3F 01 F8 0F C0 7E 10 EB F5 C7'
2022-12-30 10:39:09.876272-0800 [40936:5138438] Too few bits left in input buffer
I'm not very knowledgable about how audio works beneath the hood but I figured this is pretty basic audio stuff.
How I set up the recorder (only done once when VC is loaded):
func setupAudioRecorder() {
// Set the audio file
let audioFileURL = getFileUrl()
// Setup audio session
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playAndRecord, mode: .default, options: [])
} catch _ {
}
// Define the recorder setting
let recorderSetting = [AVFormatIDKey: NSNumber(value: kAudioFormatMPEG4AAC as UInt32),
AVSampleRateKey: 44100.0,
AVNumberOfChannelsKey: 2 ]
audioRecorder = try? AVAudioRecorder(url: audioFileURL, settings: recorderSetting)
audioRecorder?.delegate = self
audioRecorder?.isMeteringEnabled = true
audioRecorder?.prepareToRecord()
}
func getDocumentsDirectory() -> URL
{
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
func getFileUrl() -> URL
{
let timeInterval = Int(NSDate().timeIntervalSince1970*1000)
let audioFileName = "version_" + String(timeInterval) + ".m4a"
let filePath = getDocumentsDirectory().appendingPathComponent(audioFileName)
return filePath
}
Start recording:
func startRecording() {
if let recorder = audioRecorder {
if !recorder.isRecording {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(true)
} catch _ {
}
// Start recording
recorder.record()
print("RECORD " + recorder.url.absoluteString)
}
}
}
How I set up the player (called every time user hits play):
func setUpPlayer() {
guard let _ = self.audioPlayer else {
self.audioPlayer = try? AVAudioPlayer(contentsOf: self.audioRecorder!.url)
self.audioPlayer?.delegate = self
setAudioPlayerToUseSpeaker()
return
}
}
Toggle player:
func toggleAudioPlayer() {
if let audioPlayer = self.audioPlayer {
if (audioPlayer.isPlaying) {
audioPlayer.stop()
} else {
audioPlayer.play()
}
}
}

GraphicsMagick .toBuffer() creates empty buffer stream

I have a Firebase Cloud Function that converts a buffer (from PDF) to a PNG using GraphcisMagick. When I attempt to write this PNG buffer to Firebase Storage, I get a file stub but no content (empty file). My conversion to PNG is failing...
async function createThumbnail(newthumbname, mimetype, filebuffer) {
const file = bucket.file(newthumbname)
const thumbstream = file.createWriteStream({metadata:{contentType:mimetype}})
const gm = require('gm').subClass({imageMagick: true})
gm(filebuffer)
.toBuffer('png', (err, thumbbuffer)=>{
console.log(filebuffer)
console.log(thumbbuffer)
thumbstream.end(thumbbuffer)
})
}
The filebuffer passed into the createThumbnail() has content,
<Buffer 25 50 44 46 2d 31 2e 33 0a 25 c4 e5 f2 e5 eb a7 f3 a0 d0 c4 c6 0a 33 20 30 20 6f 62 6a 0a 3c 3c 20 2f 46 69 6c 74 65 72 20 2f 46 6c 61 74 65 44 65 63 ... 6464 more bytes>
But the gm(filebuffer).toBuffer() is producing and empty thumbbuffer with Error: Stream yields empty buffer
What am I doing wrong here?
This appears to be a png issue, as jpg seems to work with both, .stream() and .toBuffer().
I'll settle for jpg until I can figure out what's wrong with png.
async function createThumbnail(newthumbname, mimetype, filebuffer) {
const file = bucket.file(newthumbname)
const thumbstream = file.createWriteStream({metadata:{contentType:mimetype}})
const gm = require('gm').subClass({imageMagick: true})
gm(filebuffer)
// .setFormat("jpg")
// .stream()
// .pipe(thumbstream)
.toBuffer('jpg', (err, thumbbuffer)=>{
thumbstream.end(thumbbuffer)
})
}

String returns only numbers after separatedBy

I´m trying to separate a string like the following:
let path = "/Users/user/Downloads/history.csv"
do {
let contents = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue )
let rows = contents.components(separatedBy: "\n")
print("contents: \(contents)")
print("rows: \(rows)")
}
catch {
}
I have two files, which are looking almost identical.
From the first file the output is like this:
Output File1:
contents: 2017-07-31 16:29:53,0.10109999,9.74414271,0.98513273,0.15%,42302999779,-0.98513273,9.72952650
2017-07-31 16:29:53,0.10109999,0.25585729,0.02586716,0.25%,42302999779,-0.02586716,0.25521765
rows: ["2017-07-31 16:29:53,0.10109999,9.74414271,0.98513273,0.15%,42302999779,-0.98513273,9.72952650", "2017-07-31 16:29:53,0.10109999,0.25585729,0.02586716,0.25%,42302999779,-0.02586716,0.25521765", "", ""]
Output File2:
contents: 40.75013313,0.00064825,5/18/2017 7:17:01 PM
19.04004820,0.00059900,5/19/2017 9:17:03 PM
rows: ["4\00\0.\07\05\00\01\03\03\01\03\0,\00\0.\00\00\00\06\04\08\02\05\0,\05\0/\01\08\0/\02\00\01\07\0 \07\0:\01\07\0:\00\01\0 \0P\0M\0", "\0", "1\09\0.\00\04\00\00\04\08\02\00\0,\00\0.\00\00\00\05\09\09\00\00\0,\0\05\0/\01\09\0/\02\00\01\07\0 \09\0:\01\07\0:\00\03\0 \0P\0M\0", "\0", "\0", "\0"]
So both files are readable as String because the print(content) is working.
But as soon as the string gets separated, the second file is not readable anymore.
I tried different encodings, but nothing worked. Has anyone an idea, how to force the string to the second file, to remain a readable string?
Your file is apparently UTF-16 (little-endian) encoded:
$ hexdump fullorders4.csv
0000000 4f 00 72 00 64 00 65 00 72 00 55 00 75 00 69 00
0000010 64 00 2c 00 45 00 78 00 63 00 68 00 61 00 6e 00
0000020 67 00 65 00 2c 00 54 00 79 00 70 00 65 00 2c 00
0000030 51 00 75 00 61 00 6e 00 74 00 69 00 74 00 79 00
...
For ASCII characters, the first byte of the UTF-16 encoding is the
ASCII code, and the second byte is zero.
If the file is read as UTF-8 then the zeros are converted to an
ASCII NUL character, that is what you see as \0 in the output.
Therefore specifying the encoding as utf16LittleEndian works
in your case:
let contents = try NSString(contentsOfFile: path, encoding: String.Encoding.utf16LittleEndian.rawValue)
// or:
let contents = try String(contentsOfFile: path, encoding: .utf16LittleEndian)
There is also a method which tries to detect the used encoding
(compare iOS: What's the best way to detect a file's encoding). In Swift that would be
var enc: UInt = 0
let contents = try NSString(contentsOfFile: path, usedEncoding: &enc)
// or:
var enc = String.Encoding.ascii
let contents = try String(contentsOfFile: path, usedEncoding: &enc)
However, in your particular case, that would read the file as UTF-8
again because it is valid UTF-8. Prepending a byte order mark (BOM)
to the file (FF FE for UTF-16 little-endian) would solve that
problem reliably.

Write python code in delphi AES MODE ECB

I translated two functions in delphi but i don't know if they are right, I need to write the def do_aes_encrypt(key2_t_xor) to know if I am right.
This is what I wrote in delphi:
function key_transform (old_key:string): string;
var
x :integer;
begin
result:='';
for x := 32 downto 0 do
result:= result + chr(ord(old_key[x-1])-( x mod $0C)) ;
end;
function key_xoring ( key2_t :string ; kilo_challenge :string) : string ;
var
i :integer;
begin
result := '';
i:=0 ;
while i <= 28 do begin
result := result + chr(ord(key2_t[i+1]) xor ord(kilo_challenge[3]));
result := result + chr(ord(key2_t[i+2]) xor ord(kilo_challenge[2])) ;
result := result+ chr(ord(key2_t[i+3]) xor ord (kilo_challenge[1])) ;
i := i + 4 ;
end;
end;
This is the original python code:
def key_transform(old_key):
new_key = ''
for x in range(32,0,-1):
new_key += chr(ord(old_key[x-1]) - (x % 0x0C))
return new_key
def key_xoring(key2_t, kilo_challenge):
key2_t_xor = ''
i = 0
while i <= 28:
key2_t_xor += chr(ord(key2_t[i]) ^ ord(kilo_challenge[3]))
key2_t_xor += chr(ord(key2_t[i+1]) ^ ord(kilo_challenge[2]))
key2_t_xor += chr(ord(key2_t[i+2]) ^ ord(kilo_challenge[1]))
key2_t_xor += chr(ord(key2_t[i+3]) ^ ord(kilo_challenge[0]))
i = i + 4
return key2_t_xor
def do_aes_encrypt(key2_t_xor):
plaintext = b''
for k in range(0,16):
plaintext += chr(k)
obj = AES.new(key2_t_xor, AES.MODE_ECB)
return obj.encrypt(plaintext)
/////////////////////////////////////////////////////////////////////////////
{
kilo_challenge = kilo_header[8:12]
chalstring = ":".join("{:02x}".format(ord(k)) for k in kilo_challenge)
key2 = 'qndiakxxuiemdklseqid~a~niq,zjuxl' # if this doesnt work try 'lgowvqnltpvtgogwswqn~n~mtjjjqxro'
kilo_response = do_aes_encrypt(key_xoring(key_transform(key2),kilo_challenge))}
this code is for calculate data line 16 byte to be send as an addition to 32 byte
before
look photo the marked line in blue is what i need to calculate by the 4 byte hex befor marked in porple
and this is the key
key2 = 'qndiakxxuiemdklseqid~a~niq,zjuxl'
in delphi
because python code is working perfect
look to the photo
how it work
this is for lg phones upgrading firmware when i receive the KILOCENT ANSOWER AS THE photo show`s
this below change every time phone connected
||
V
4b 49 4c 4f 43 45 4e 54 ([ac e5 b1 06]) 00 00 00 00 KILOCENT¬å±.....
00 00 00 00 00 00 00 00 30 d4 00 00 b4 b6 b3 b0 ........0Ô..´¶³°
i have to send KILOMETER REQUEST to phone the first and second line is fixed no change but the third i have to change it by the AES ECB MODE encryption look
4b 49 4c 4f 4d 45 54 52 00 00 00 00 02 00 00 00 KILOMETR........
00 00 00 00 10 00 00 00 85 b6 00 00 b4 b6 b3 b0 ........…¶..´¶³°
fc 21 d8 e5 5b aa fd 58 1e 33 58 fd e9 0b 65 38 ü!Øå[ªýX.3Xýé.e8 <==this
and this is old key
key2 = 'qndiakxxuiemdklseqid~a~niq,zjuxl'

Resources