Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
2e95d9f0
Commit
2e95d9f0
authored
Aug 08, 2020
by
vvb2060
Committed by
John Wu
Aug 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update to APK Signature Scheme v2
parent
fe238839
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1208 additions
and
536 deletions
+1208
-536
ApkSignerV2.java
...ning/src/main/java/com/topjohnwu/signing/ApkSignerV2.java
+772
-0
SignApk.java
app/signing/src/main/java/com/topjohnwu/signing/SignApk.java
+286
-242
ZipAdjust.java
...igning/src/main/java/com/topjohnwu/signing/ZipAdjust.java
+0
-277
ZipSigner.java
...igning/src/main/java/com/topjohnwu/signing/ZipSigner.java
+8
-9
ZipUtils.java
...signing/src/main/java/com/topjohnwu/signing/ZipUtils.java
+136
-0
Keygen.kt
app/src/main/java/com/topjohnwu/magisk/core/utils/Keygen.kt
+1
-1
PatchAPK.kt
...src/main/java/com/topjohnwu/magisk/core/utils/PatchAPK.kt
+5
-7
No files found.
app/signing/src/main/java/com/topjohnwu/signing/ApkSignerV2.java
0 → 100644
View file @
2e95d9f0
This diff is collapsed.
Click to expand it.
app/signing/src/main/java/com/topjohnwu/signing/SignA
PK
.java
→
app/signing/src/main/java/com/topjohnwu/signing/SignA
pk
.java
View file @
2e95d9f0
This diff is collapsed.
Click to expand it.
app/signing/src/main/java/com/topjohnwu/signing/ZipAdjust.java
deleted
100644 → 0
View file @
fe238839
This diff is collapsed.
Click to expand it.
app/signing/src/main/java/com/topjohnwu/signing/ZipSigner.java
View file @
2e95d9f0
...
...
@@ -6,7 +6,6 @@ import java.io.FileInputStream;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.security.KeyStore
;
import
java.security.KeyStoreException
;
import
java.security.NoSuchAlgorithmException
;
...
...
@@ -28,20 +27,20 @@ public class ZipSigner {
System
.
exit
(
2
);
}
private
static
void
sign
(
JarMap
input
,
OutputStream
output
)
throws
Exception
{
sign
(
SignA
PK
.
class
.
getResourceAsStream
(
"/keys/testkey.x509.pem"
),
SignA
PK
.
class
.
getResourceAsStream
(
"/keys/testkey.pk8"
),
input
,
output
);
private
static
void
sign
(
JarMap
input
,
File
OutputStream
output
)
throws
Exception
{
sign
(
SignA
pk
.
class
.
getResourceAsStream
(
"/keys/testkey.x509.pem"
),
SignA
pk
.
class
.
getResourceAsStream
(
"/keys/testkey.pk8"
),
input
,
output
);
}
private
static
void
sign
(
InputStream
certIs
,
InputStream
keyIs
,
JarMap
input
,
OutputStream
output
)
throws
Exception
{
JarMap
input
,
File
OutputStream
output
)
throws
Exception
{
X509Certificate
cert
=
CryptoUtils
.
readCertificate
(
certIs
);
PrivateKey
key
=
CryptoUtils
.
readPrivateKey
(
keyIs
);
SignA
PK
.
signAndAdjust
(
cert
,
key
,
input
,
output
);
SignA
pk
.
sign
(
cert
,
key
,
input
,
output
);
}
private
static
void
sign
(
String
keyStore
,
String
keyStorePass
,
String
alias
,
String
keyPass
,
JarMap
in
,
OutputStream
out
)
throws
Exception
{
JarMap
in
,
File
OutputStream
out
)
throws
Exception
{
KeyStore
ks
;
try
{
ks
=
KeyStore
.
getInstance
(
"JKS"
);
...
...
@@ -56,7 +55,7 @@ public class ZipSigner {
}
X509Certificate
cert
=
(
X509Certificate
)
ks
.
getCertificate
(
alias
);
PrivateKey
key
=
(
PrivateKey
)
ks
.
getKey
(
alias
,
keyPass
.
toCharArray
());
SignA
PK
.
signAndAdjust
(
cert
,
key
,
in
,
out
);
SignA
pk
.
sign
(
cert
,
key
,
in
,
out
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
...
...
@@ -66,7 +65,7 @@ public class ZipSigner {
Security
.
insertProviderAt
(
new
BouncyCastleProvider
(),
1
);
try
(
JarMap
in
=
JarMap
.
open
(
args
[
args
.
length
-
2
],
false
);
OutputStream
out
=
new
FileOutputStream
(
args
[
args
.
length
-
1
]))
{
File
OutputStream
out
=
new
FileOutputStream
(
args
[
args
.
length
-
1
]))
{
if
(
args
.
length
==
2
)
{
sign
(
in
,
out
);
}
else
if
(
args
.
length
==
4
)
{
...
...
app/signing/src/main/java/com/topjohnwu/signing/ZipUtils.java
0 → 100644
View file @
2e95d9f0
package
com
.
topjohnwu
.
signing
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
/**
* Assorted ZIP format helpers.
*
* <p>NOTE: Most helper methods operating on {@code ByteBuffer} instances expect that the byte
* order of these buffers is little-endian.
*/
public
abstract
class
ZipUtils
{
private
static
final
int
ZIP_EOCD_REC_MIN_SIZE
=
22
;
private
static
final
int
ZIP_EOCD_REC_SIG
=
0x06054b50
;
private
static
final
int
ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET
=
12
;
private
static
final
int
ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET
=
16
;
private
static
final
int
ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET
=
20
;
private
static
final
int
ZIP64_EOCD_LOCATOR_SIZE
=
20
;
private
static
final
int
ZIP64_EOCD_LOCATOR_SIG
=
0x07064b50
;
private
static
final
int
UINT16_MAX_VALUE
=
0xffff
;
private
ZipUtils
()
{
}
/**
* Returns the position at which ZIP End of Central Directory record starts in the provided
* buffer or {@code -1} if the record is not present.
*
* <p>NOTE: Byte order of {@code zipContents} must be little-endian.
*/
public
static
int
findZipEndOfCentralDirectoryRecord
(
ByteBuffer
zipContents
)
{
assertByteOrderLittleEndian
(
zipContents
);
// ZIP End of Central Directory (EOCD) record is located at the very end of the ZIP archive.
// The record can be identified by its 4-byte signature/magic which is located at the very
// beginning of the record. A complication is that the record is variable-length because of
// the comment field.
// The algorithm for locating the ZIP EOCD record is as follows. We search backwards from
// end of the buffer for the EOCD record signature. Whenever we find a signature, we check
// the candidate record's comment length is such that the remainder of the record takes up
// exactly the remaining bytes in the buffer. The search is bounded because the maximum
// size of the comment field is 65535 bytes because the field is an unsigned 16-bit number.
int
archiveSize
=
zipContents
.
capacity
();
if
(
archiveSize
<
ZIP_EOCD_REC_MIN_SIZE
)
{
return
-
1
;
}
int
maxCommentLength
=
Math
.
min
(
archiveSize
-
ZIP_EOCD_REC_MIN_SIZE
,
UINT16_MAX_VALUE
);
int
eocdWithEmptyCommentStartPosition
=
archiveSize
-
ZIP_EOCD_REC_MIN_SIZE
;
for
(
int
expectedCommentLength
=
0
;
expectedCommentLength
<
maxCommentLength
;
expectedCommentLength
++)
{
int
eocdStartPos
=
eocdWithEmptyCommentStartPosition
-
expectedCommentLength
;
if
(
zipContents
.
getInt
(
eocdStartPos
)
==
ZIP_EOCD_REC_SIG
)
{
int
actualCommentLength
=
getUnsignedInt16
(
zipContents
,
eocdStartPos
+
ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET
);
if
(
actualCommentLength
==
expectedCommentLength
)
{
return
eocdStartPos
;
}
}
}
return
-
1
;
}
/**
* Returns {@code true} if the provided buffer contains a ZIP64 End of Central Directory
* Locator.
*
* <p>NOTE: Byte order of {@code zipContents} must be little-endian.
*/
public
static
boolean
isZip64EndOfCentralDirectoryLocatorPresent
(
ByteBuffer
zipContents
,
int
zipEndOfCentralDirectoryPosition
)
{
assertByteOrderLittleEndian
(
zipContents
);
// ZIP64 End of Central Directory Locator immediately precedes the ZIP End of Central
// Directory Record.
int
locatorPosition
=
zipEndOfCentralDirectoryPosition
-
ZIP64_EOCD_LOCATOR_SIZE
;
if
(
locatorPosition
<
0
)
{
return
false
;
}
return
zipContents
.
getInt
(
locatorPosition
)
==
ZIP64_EOCD_LOCATOR_SIG
;
}
/**
* Returns the offset of the start of the ZIP Central Directory in the archive.
*
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
*/
public
static
long
getZipEocdCentralDirectoryOffset
(
ByteBuffer
zipEndOfCentralDirectory
)
{
assertByteOrderLittleEndian
(
zipEndOfCentralDirectory
);
return
getUnsignedInt32
(
zipEndOfCentralDirectory
,
zipEndOfCentralDirectory
.
position
()
+
ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET
);
}
/**
* Sets the offset of the start of the ZIP Central Directory in the archive.
*
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
*/
public
static
void
setZipEocdCentralDirectoryOffset
(
ByteBuffer
zipEndOfCentralDirectory
,
long
offset
)
{
assertByteOrderLittleEndian
(
zipEndOfCentralDirectory
);
setUnsignedInt32
(
zipEndOfCentralDirectory
,
zipEndOfCentralDirectory
.
position
()
+
ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET
,
offset
);
}
/**
* Returns the size (in bytes) of the ZIP Central Directory.
*
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
*/
public
static
long
getZipEocdCentralDirectorySizeBytes
(
ByteBuffer
zipEndOfCentralDirectory
)
{
assertByteOrderLittleEndian
(
zipEndOfCentralDirectory
);
return
getUnsignedInt32
(
zipEndOfCentralDirectory
,
zipEndOfCentralDirectory
.
position
()
+
ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET
);
}
private
static
void
assertByteOrderLittleEndian
(
ByteBuffer
buffer
)
{
if
(
buffer
.
order
()
!=
ByteOrder
.
LITTLE_ENDIAN
)
{
throw
new
IllegalArgumentException
(
"ByteBuffer byte order must be little endian"
);
}
}
private
static
int
getUnsignedInt16
(
ByteBuffer
buffer
,
int
offset
)
{
return
buffer
.
getShort
(
offset
)
&
0xffff
;
}
private
static
long
getUnsignedInt32
(
ByteBuffer
buffer
,
int
offset
)
{
return
buffer
.
getInt
(
offset
)
&
0xffffffff
L
;
}
private
static
void
setUnsignedInt32
(
ByteBuffer
buffer
,
int
offset
,
long
value
)
{
if
((
value
<
0
)
||
(
value
>
0xffffffff
L
))
{
throw
new
IllegalArgumentException
(
"uint32 value of out range: "
+
value
);
}
buffer
.
putInt
(
buffer
.
position
()
+
offset
,
(
int
)
value
);
}
}
app/src/main/java/com/topjohnwu/magisk/core/utils/Keygen.kt
View file @
2e95d9f0
...
...
@@ -39,7 +39,7 @@ class Keygen(context: Context) : CertKeyProvider {
}
private
val
start
=
Calendar
.
getInstance
().
apply
{
add
(
Calendar
.
MONTH
,
-
3
)
}
private
val
end
=
Calendar
.
getInstance
()
.
apply
{
add
(
Calendar
.
YEAR
,
30
)
}
private
val
end
=
start
.
apply
{
add
(
Calendar
.
YEAR
,
30
)
}
override
val
cert
get
()
=
provider
.
cert
override
val
key
get
()
=
provider
.
key
...
...
app/src/main/java/com/topjohnwu/magisk/core/utils/PatchAPK.kt
View file @
2e95d9f0
...
...
@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.data.network.GithubRawServices
import
com.topjohnwu.magisk.ktx.get
import
com.topjohnwu.magisk.ktx.writeTo
import
com.topjohnwu.signing.JarMap
import
com.topjohnwu.signing.SignA
PK
import
com.topjohnwu.signing.SignA
pk
import
com.topjohnwu.superuser.Shell
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
...
...
@@ -29,10 +29,8 @@ import java.security.SecureRandom
object
PatchAPK
{
private
const
val
ALPHA
=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
private
const
val
DIGITS
=
"0123456789"
const
val
ALPHANUM
=
ALPHA
+
DIGITS
private
const
val
ALPHANUMDOTS
=
"$ALPHANUM............"
private
const
val
ALPHA
=
"abcdefghijklmnopqrstuvwxyz"
private
const
val
ALPHADOTS
=
"$ALPHA....."
private
const
val
APP_ID
=
"com.topjohnwu.magisk"
private
const
val
APP_NAME
=
"Magisk Manager"
...
...
@@ -48,7 +46,7 @@ object PatchAPK {
next
=
if
(
prev
==
'.'
||
i
==
len
-
1
)
{
ALPHA
[
random
.
nextInt
(
ALPHA
.
length
)]
}
else
{
ALPHA
NUMDOTS
[
random
.
nextInt
(
ALPHANUM
DOTS
.
length
)]
ALPHA
DOTS
[
random
.
nextInt
(
ALPHA
DOTS
.
length
)]
}
builder
.
append
(
next
)
prev
=
next
...
...
@@ -96,7 +94,7 @@ object PatchAPK {
// Write apk changes
jar
.
getOutputStream
(
je
).
write
(
xml
)
val
keys
=
Keygen
(
get
())
SignA
PK
.
sign
(
keys
.
cert
,
keys
.
key
,
jar
,
FileOutputStream
(
out
).
buffered
(
))
SignA
pk
.
sign
(
keys
.
cert
,
keys
.
key
,
jar
,
FileOutputStream
(
out
))
}
catch
(
e
:
Exception
)
{
Timber
.
e
(
e
)
return
false
...
...
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