Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
matrix-org
Olm
Commits
f709b062
Commit
f709b062
authored
Jun 28, 2018
by
Hubert Chathi
Browse files
add functions for pickling/unpickling a decryption object
parent
3ed0ec22
Changes
5
Show whitespace changes
Inline
Side-by-side
include/olm/pk.h
View file @
f709b062
...
...
@@ -122,6 +122,36 @@ size_t olm_pk_generate_key(
void
*
random
,
size_t
random_length
);
/** Returns the number of bytes needed to store a decryption object. */
size_t
olm_pickle_pk_decryption_length
(
OlmPkDecryption
*
decryption
);
/** Stores decryption object as a base64 string. Encrypts the object using the
* supplied key. Returns the length of the pickled object on success.
* Returns olm_error() on failure. If the pickle output buffer
* is smaller than olm_pickle_account_length() then
* olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
size_t
olm_pickle_pk_decryption
(
OlmPkDecryption
*
decryption
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
);
/** Loads a decryption object from a pickled base64 string. The associated
* public key will be written to the pubkey buffer. Decrypts the object using
* the supplied key. Returns olm_error() on failure. If the key doesn't
* match the one used to encrypt the account then olm_pk_decryption_last_error()
* will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
* olm_pk_decryption_last_error() will be "INVALID_BASE64". The input pickled
* buffer is destroyed */
size_t
olm_unpickle_pk_decryption
(
OlmPkDecryption
*
decryption
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
,
void
*
pubkey
,
size_t
pubkey_length
);
/** Get the length of the plaintext that will correspond to a ciphertext of the
* given length. */
size_t
olm_pk_max_plaintext_length
(
...
...
javascript/olm_pk.js
View file @
f709b062
...
...
@@ -135,6 +135,35 @@ PkDecryption.prototype['generate_key'] = restore_stack(function () {
return
Pointer_stringify
(
pubkey_buffer
);
});
PkDecryption
.
prototype
[
'
pickle
'
]
=
restore_stack
(
function
(
key
)
{
var
key_array
=
array_from_string
(
key
);
var
pickle_length
=
pk_decryption_method
(
Module
[
'
_olm_pickle_pk_decryption_length
'
]
)(
this
.
ptr
);
var
key_buffer
=
stack
(
key_array
);
var
pickle_buffer
=
stack
(
pickle_length
+
NULL_BYTE_PADDING_LENGTH
);
pk_decryption_method
(
Module
[
'
_olm_pickle_pk_decryption
'
])(
this
.
ptr
,
key_buffer
,
key_array
.
length
,
pickle_buffer
,
pickle_length
);
return
Pointer_stringify
(
pickle_buffer
);
});
PkDecryption
.
prototype
[
'
unpickle
'
]
=
restore_stack
(
function
(
key
,
pickle
)
{
var
key_array
=
array_from_string
(
key
);
var
key_buffer
=
stack
(
key_array
);
var
pickle_array
=
array_from_string
(
pickle
);
var
pickle_buffer
=
stack
(
pickle_array
);
var
ephemeral_length
=
pk_decryption_method
(
Module
[
"
_olm_pk_key_length
"
]
)();
var
ephemeral_buffer
=
stack
(
ephemeral_length
+
NULL_BYTE_PADDING_LENGTH
);
pk_decryption_method
(
Module
[
'
_olm_unpickle_pk_decryption
'
])(
this
.
ptr
,
key_buffer
,
key_array
.
length
,
pickle_buffer
,
pickle_array
.
length
,
ephemeral_buffer
,
ephemeral_length
);
return
Pointer_stringify
(
ephemeral_buffer
);
});
PkDecryption
.
prototype
[
'
decrypt
'
]
=
restore_stack
(
function
(
ephemeral_key
,
mac
,
ciphertext
)
{
...
...
javascript/test/pk.spec.js
View file @
f709b062
...
...
@@ -61,4 +61,22 @@ describe("pk", function() {
console
.
log
(
TEST_TEXT
,
"
->
"
,
decrypted
);
expect
(
decrypted
).
toEqual
(
TEST_TEXT
);
});
it
(
'
should pickle and unpickle
'
,
function
()
{
var
TEST_TEXT
=
'
têst1
'
;
var
pubkey
=
decryption
.
generate_key
();
encryption
.
set_recipient_key
(
pubkey
);
var
encrypted
=
encryption
.
encrypt
(
TEST_TEXT
);
var
PICKLE_KEY
=
'
secret_key
'
;
var
pickle
=
decryption
.
pickle
(
PICKLE_KEY
);
var
new_decryption
=
new
Olm
.
PkDecryption
();
var
new_pubkey
=
new_decryption
.
unpickle
(
PICKLE_KEY
,
pickle
);
expect
(
new_pubkey
).
toEqual
(
pubkey
);
var
decrypted
=
new_decryption
.
decrypt
(
encrypted
.
ephemeral
,
encrypted
.
mac
,
encrypted
.
ciphertext
);
console
.
log
(
TEST_TEXT
,
"
->
"
,
decrypted
);
expect
(
decrypted
).
toEqual
(
TEST_TEXT
);
new_decryption
.
free
();
});
});
src/pk.cpp
View file @
f709b062
...
...
@@ -19,6 +19,8 @@
#include "olm/error.h"
#include "olm/memory.hh"
#include "olm/base64.hh"
#include "olm/pickle_encoding.h"
#include "olm/pickle.hh"
extern
"C"
{
...
...
@@ -203,6 +205,106 @@ size_t olm_pk_generate_key(
return
0
;
}
namespace
{
static
const
std
::
uint32_t
PK_DECRYPTION_PICKLE_VERSION
=
1
;
static
std
::
size_t
pickle_length
(
OlmPkDecryption
const
&
value
)
{
std
::
size_t
length
=
0
;
length
+=
olm
::
pickle_length
(
PK_DECRYPTION_PICKLE_VERSION
);
length
+=
olm
::
pickle_length
(
value
.
key_pair
);
return
length
;
}
static
std
::
uint8_t
*
pickle
(
std
::
uint8_t
*
pos
,
OlmPkDecryption
const
&
value
)
{
pos
=
olm
::
pickle
(
pos
,
PK_DECRYPTION_PICKLE_VERSION
);
pos
=
olm
::
pickle
(
pos
,
value
.
key_pair
);
return
pos
;
}
static
std
::
uint8_t
const
*
unpickle
(
std
::
uint8_t
const
*
pos
,
std
::
uint8_t
const
*
end
,
OlmPkDecryption
&
value
)
{
uint32_t
pickle_version
;
pos
=
olm
::
unpickle
(
pos
,
end
,
pickle_version
);
switch
(
pickle_version
)
{
case
1
:
break
;
default:
value
.
last_error
=
OlmErrorCode
::
OLM_UNKNOWN_PICKLE_VERSION
;
return
end
;
}
pos
=
olm
::
unpickle
(
pos
,
end
,
value
.
key_pair
);
return
pos
;
}
}
size_t
olm_pickle_pk_decryption_length
(
OlmPkDecryption
*
decryption
)
{
return
_olm_enc_output_length
(
pickle_length
(
*
decryption
));
}
size_t
olm_pickle_pk_decryption
(
OlmPkDecryption
*
decryption
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
)
{
OlmPkDecryption
&
object
=
*
decryption
;
std
::
size_t
raw_length
=
pickle_length
(
object
);
if
(
pickled_length
<
_olm_enc_output_length
(
raw_length
))
{
object
.
last_error
=
OlmErrorCode
::
OLM_OUTPUT_BUFFER_TOO_SMALL
;
return
std
::
size_t
(
-
1
);
}
pickle
(
_olm_enc_output_pos
(
reinterpret_cast
<
std
::
uint8_t
*>
(
pickled
),
raw_length
),
object
);
return
_olm_enc_output
(
reinterpret_cast
<
std
::
uint8_t
const
*>
(
key
),
key_length
,
reinterpret_cast
<
std
::
uint8_t
*>
(
pickled
),
raw_length
);
}
size_t
olm_unpickle_pk_decryption
(
OlmPkDecryption
*
decryption
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
,
void
*
pubkey
,
size_t
pubkey_length
)
{
OlmPkDecryption
&
object
=
*
decryption
;
if
(
pubkey
!=
NULL
&&
pubkey_length
<
olm_pk_key_length
())
{
object
.
last_error
=
OlmErrorCode
::
OLM_OUTPUT_BUFFER_TOO_SMALL
;
return
std
::
size_t
(
-
1
);
}
std
::
uint8_t
*
const
pos
=
reinterpret_cast
<
std
::
uint8_t
*>
(
pickled
);
std
::
size_t
raw_length
=
_olm_enc_input
(
reinterpret_cast
<
std
::
uint8_t
const
*>
(
key
),
key_length
,
pos
,
pickled_length
,
&
object
.
last_error
);
if
(
raw_length
==
std
::
size_t
(
-
1
))
{
return
std
::
size_t
(
-
1
);
}
std
::
uint8_t
*
const
end
=
pos
+
raw_length
;
/* On success unpickle will return (pos + raw_length). If unpickling
* terminates too soon then it will return a pointer before
* (pos + raw_length). On error unpickle will return (pos + raw_length + 1).
*/
if
(
end
!=
unpickle
(
pos
,
end
+
1
,
object
))
{
if
(
object
.
last_error
==
OlmErrorCode
::
OLM_SUCCESS
)
{
object
.
last_error
=
OlmErrorCode
::
OLM_CORRUPTED_PICKLE
;
}
return
std
::
size_t
(
-
1
);
}
if
(
pubkey
!=
NULL
)
{
olm
::
encode_base64
((
const
uint8_t
*
)
object
.
key_pair
.
public_key
.
public_key
,
CURVE25519_KEY_LENGTH
,
(
uint8_t
*
)
pubkey
);
}
return
pickled_length
;
}
size_t
olm_pk_max_plaintext_length
(
OlmPkDecryption
*
decryption
,
size_t
ciphertext_length
...
...
tests/test_pk.cpp
View file @
f709b062
...
...
@@ -87,4 +87,75 @@ free(plaintext_buffer);
}
{
/* Encryption Test Case 1 */
TestCase
test_case
(
"Public Key Decryption pickling"
);
std
::
uint8_t
decryption_buffer
[
olm_pk_decryption_size
()];
OlmPkDecryption
*
decryption
=
olm_pk_decryption
(
decryption_buffer
);
std
::
uint8_t
alice_private
[
32
]
=
{
0x77
,
0x07
,
0x6D
,
0x0A
,
0x73
,
0x18
,
0xA5
,
0x7D
,
0x3C
,
0x16
,
0xC1
,
0x72
,
0x51
,
0xB2
,
0x66
,
0x45
,
0xDF
,
0x4C
,
0x2F
,
0x87
,
0xEB
,
0xC0
,
0x99
,
0x2A
,
0xB1
,
0x77
,
0xFB
,
0xA5
,
0x1D
,
0xB9
,
0x2C
,
0x2A
};
const
std
::
uint8_t
*
alice_public
=
(
std
::
uint8_t
*
)
"hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmoK"
;
std
::
uint8_t
pubkey
[
olm_pk_key_length
()];
olm_pk_generate_key
(
decryption
,
pubkey
,
sizeof
(
pubkey
),
alice_private
,
sizeof
(
alice_private
)
);
const
uint8_t
*
PICKLE_KEY
=
(
uint8_t
*
)
"secret_key"
;
std
::
uint8_t
pickle_buffer
[
olm_pickle_pk_decryption_length
(
decryption
)];
const
uint8_t
*
expected_pickle
=
(
uint8_t
*
)
"qx37WTQrjZLz5tId/uBX9B3/okqAbV1ofl9UnHKno1eipByCpXleAAlAZoJgYnCDOQZDQWzo3luTSfkF9pU1mOILCbbouubs6TVeDyPfgGD9i86J8irHjA"
;
olm_pickle_pk_decryption
(
decryption
,
PICKLE_KEY
,
strlen
((
char
*
)
PICKLE_KEY
),
pickle_buffer
,
sizeof
(
pickle_buffer
)
);
assert_equals
(
expected_pickle
,
pickle_buffer
,
olm_pickle_pk_decryption_length
(
decryption
));
olm_clear_pk_decryption
(
decryption
);
memset
(
pubkey
,
0
,
olm_pk_key_length
());
olm_unpickle_pk_decryption
(
decryption
,
PICKLE_KEY
,
strlen
((
char
*
)
PICKLE_KEY
),
pickle_buffer
,
sizeof
(
pickle_buffer
),
pubkey
,
sizeof
(
pubkey
)
);
assert_equals
(
alice_public
,
pubkey
,
olm_pk_key_length
());
char
*
ciphertext
=
strdup
(
"ntk49j/KozVFtSqJXhCejg"
);
const
char
*
mac
=
"zpzU6BkZcNI"
;
const
char
*
ephemeral_key
=
"3p7bfXt9wbTTW2HC7OQ1Nz+DQ8hbeGdNrfx+FG+IK08"
;
size_t
max_plaintext_length
=
olm_pk_max_plaintext_length
(
decryption
,
strlen
(
ciphertext
));
std
::
uint8_t
*
plaintext_buffer
=
(
std
::
uint8_t
*
)
malloc
(
max_plaintext_length
);
olm_pk_decrypt
(
decryption
,
ephemeral_key
,
strlen
(
ephemeral_key
),
mac
,
strlen
(
mac
),
ciphertext
,
strlen
(
ciphertext
),
plaintext_buffer
,
max_plaintext_length
);
const
std
::
uint8_t
*
plaintext
=
(
std
::
uint8_t
*
)
"This is a test"
;
assert_equals
(
plaintext
,
plaintext_buffer
,
strlen
((
const
char
*
)
plaintext
));
free
(
ciphertext
);
free
(
plaintext_buffer
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment