Compile
To get back to the point, continue talking about the Signal server. Firstly, the current code for Signal Server is version 2.92. Since there is an engineering file pom.xml, it should be compiled using Maven. The warehouse address is https://github.com/signalapp/Signal-Server/ .
mvn install -DskipTests
Compiling this version of code requires JDK 11+. If you use a lower version of JDK (such as in Ubuntu 16.04), Maven will report an error related to the number 11. If you are not familiar with it, this seemingly inexplicable error message may make you scratching your head for a while and become a pit. The final product of compilation is TextSecureServer-3.21. jar.
Guide to Finding Others' Installation Experience
Compiled, now we need to deploy. First, Google the keywords Signal Server+Install/Deploy, and the most frequently cited one is the 1.88 version of the installation guide: "Signal Server Installation Guide". I guess this student may have used this post as a diversion to collect some consulting fees, so I didn't write it in that detail. But in the absence of official documents, this guide is also a good start (applause here), so we can only follow this for now.
The main entrance for configuration: template file sample.yml
Take out the configuration template file sample.yaml from the Signal Server code repository and rename it to config.yml. Follow the above guide to configure, and you will find some changes to the configuration items in section 3.21. The later facts will prove that the yml template in the code repository is an old version that does not match the code at all, and it is almost useless to follow this configuration.
Account application for third-party interfaces
First, search for the third-party interface accounts that need to be applied for in yml and apply one by one.
List of accounts to apply for
- Twilio
- S3 minIO can replace
- SQS
- reCAPTCHA
- GCM
- APN
Configure the domain name of the server
If you don't have a domain name, buy one. HTTPS/WSS (WebSocket Secure) services require verifying the certificate corresponding to the domain name, and the reverse connection of the Twilio service also requires configuring the domain name.
Install Redis:
sudo apt-get install -y redis-server
Edit config:
sudo vi /etc/redis/redis.conf
reboot Redis:
sudo systemctl restart redis.service
Install PostgreSQL
init data tables:
sudo apt-get install postgresql postgresql-contrib -y
sudo -u postgres psql -c "CREATE DATABASE accountsdb"
sudo -u postgres psql -c "CREATE DATABASE messagedb"
sudo -u postgres psql -c "CREATE DATABASE abusedb"
sudo -u postgres psql -c "CREATE DATABASE readdb"
sudo -u postgres psql -c "CREATE USER signal \
WITH ENCRYPTED PASSWORD 'password'"
edit config:
sudo vi /etc/postgresql/13/main/postgresql.conf
1、 listen_addresses='localhost' to listen_addresses='*'
2、add at last row :
host all all 0.0.0.0/0 md5
reboot database:
sudo systemctl restart postgresql
Install coturn
a real-time voice chat based on the webrtc protocol
Enable port 3478 for firewall TCP and UDP, and also enable UDP.
install:
apt-get install libevent-dev
apt-get install libevent2
download
https://github.com/coturn/coturn
Install COTURN and generate certificate:
openssl req -x509 -newkey rsa:2048 -keyout /etc/turn_server_pkey.pem -out /etc/turn_server_cert.pem -days 99999 -nodes
edit config file:
sudo vi /etc/turnserver.conf
edit field below:
$ sudo find / -name ssl-dhparams.pem
/usr/lib/python3/dist-packages/certbot/ssl-dhparams.pem
listening-ip=
external-ip=
use-auth-secret
static-auth-secret=
user=user1:password1
realm=www.yourdomain.com
cert=/etc/turn_server_cert.pem
pkey=/etc/turn_server_pkey.pem
cli-password=
dh-file=/usr/lib/python3/dist-packages/certbot/ssl-dhparams.pem
startup:
turnserver -a -f -user=zjf:123456 -r www.lxrtalk.com
Then use the following page to test the basic functions of COTURN (using Google Chrome may report error 701, it is recommended to use Firefox browser):
https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
Note: There are two authentication mechanisms for COTURN, one for username and password, and the other for shared key (secret). The shared key is used by the REST interface, and the Signal Server requires the shared key. The page used to test the basic functions of COTURN only supports username+password authentication, and COTURN prioritizes the use of shared keys. That is to say, if both shared keys and username+password are provided, it cannot be tested on the above test page. So you need to disable the setting of the shared key first, and then restore the configuration of the shared key after passing the test on this page above.
After configuring the shared key, start the daemon:
sudo turnserver -a -o -v -n -u test:test -r "www.youerdomain.com"
Install Apache 2 (can be replaced by nginx)
Open port 80 of the server to the public on the firewall, as obtaining a free certificate requires connecting back to port 80 for verification.
Next, use a2enmod to open the required Apache proxy modules, use Certbot to obtain the free HTTPS certificate corresponding to the domain name, and finally prompt to redirect port 80 to port 443.
sudo apt-get install apache2
sudo a2enmod proxy proxy_http proxy_wstunnel
sudo add-apt-repository ppa:certbot/certbot -y
sudo apt-get update -y
sudo apt-get install python-certbot-apache -y
sudo certbot --authenticator standalone --installer apache -d "www.yourdomain.com" --pre-hook "systemctl stop apache2" --post-hook "systemctl start apache2"
Edit the configuration file of Apache's HTTPS site:
Sudo vi/etc/apache2/sites available/000-default le ssl. conf
Set up a reverse proxy to reverse proxy client requests from Apache's 443 port to Signal Server's 8080 port. 443's wss://reverse proxy to 8080's wss://, 443's https://reverse proxy to 8080's http://. In addition to using port 8080 to listen to ws://and http://, Signal Server also has an 8081 internal management port that can be opened using a browser http://127.0.0.1:8081 View.
The configuration sample of HTTPS site is as follows:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster@excmple.com
DocumentRoot /var/www/html
AllowEncodedSlashes NoDecode
RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule .* "ws://localhost:8080$0" [P,L]
ProxyRequests off
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
#LogLevel trace6
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
ServerName yourdomain
SSLCertificateFile /etc/letsencrypt/live/www.yourdomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.yourdomain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
The HTTPS certificate is also required by the Signal client.
The above rules for reverse proxy are copied from "How to Reverse Proxy Websockets with Apache 2.4" through Google. This configuration first uses RewriteEngine to match the protocol promotion field in the client's wss://protocol. If there is a match, it will be forwarded to ws://, and if there is no match, ProxyPass will be used to reverse proxy to http://. However, there were three errors in the configuration in the original post that resulted in unsuccessful communication between Signal's client and server. The information provided here has been tampered with and corrected (interested parties can compare the errors themselves).
Since we encounter problems here, we need to use the two major tools of code farming: logs and debuggers. By modifying the log configuration field of the above site to LogLevel trace6, open the detailed logs of Apache and restart Apache. Then, analyze/var/log/access. log,/var/log/error. log to determine whether it is a problem with Apache or the Signal Server on port 8080.
AllowEncodedSlashes NoDecode is the sentence that needs to be added based on log analysis, as the URI sent by the iOS client to the Signal Server contains special characters such as slashes% 2F, plus signs% 2B, etc. If this sentence is not present, Apache may directly return 404 for these URIs without forwarding them to the Signal Server's 8080 port.
Install CDS
Signal's CDS (contact discovery service, mobile phone contact book contact query function, which is more complex for security reasons). CDS is generally not deployed on the same machine as Signal Server, but uses independent special hardware to ensure its security, namely Intel SGX. SGX can create a hardware isolation area called enclave (Chinese name "enclave"). Currently, only Microsoft Azure and Intel have collaborated among cloud service providers to provide a trial environment for SGX on the cloud, with geographical limitations.
Interested parties can refer to the guide written by those who have been involved in CDS, and this guide is no longer maintained:
https://github.com/on-premise-signal/signal-setup-guide。
CDS code:https://github.com/signalapp/ContactDiscoveryService。
cds needs /intel/linux-sgx https://github.com/intel/linux-sgx/tree/sgx_2.1.3#install-the-intelr-sgx-psw
Signal Server The Virgin Run
Initialize the database and create tables (we haven't delved into why we haven't processed a database named readdb yet):
java -jar TextSecureServer-3.21.jar messagedb migrate config/config.yml
java -jar TextSecureServer-3.21.jar accountdb migrate config/config.yml
java -jar TextSecureServer-3.21.jar abusedb migrate config/config.yml
After filling in the fields of config.yml, try running it:
java -jar target/TextSecureServer-3.21.jar server config/config.yml
The result was not unexpected: it couldn't run. Fortunately, the printed error message clearly indicates which configuration item has the problem, and we can only dig the code (because Signal developers have said that if there is code, there is everything). From now on, we need to start the cycle of "viewing error messages ->Google search for errors/viewing code/debugging code ->changing configuration". This is the fate of coders in the era of relying on Google for development, and we need to prepare a relatively hidden one A fast ladder ensures that Google is online 24 hours a day.
New configuration template file config.yml
Fortunately, the configuration item parsing code for Signal Server is concentrated in the file service/src/main/java/org/Whispersystems/textsecuregcm/WhisperServerConfiguration. java. Open the project using IDEA, browse to this file, find the type declaration and parsing code for each configuration item, extract them uniformly, and create a new config.yml template:
twilio:
accountId:
accountToken:
numbers: # array
localDomain:
messagingServicesId:
push:
queueSize: 200
attachments:
accessKey:
accessSecret:
bucket:
region:
cdn:
accessKey:
accessSecret:
bucket:
region:
cache:
url:
replicaUrls: # array
directory:
redis:
url:
replicaUrls: # array
sqs:
accessKey:
accessSecret:
queueUrl:
region: us-east-1
client:
userAuthenticationTokenSharedSecret: # hex string
userAuthenticationTokenUserIdSecret: # hex string
server:
replicationUrl:
replicationPassword:
replicationCaCertificate:
accountDatabaseCrawler:
chunkSize: 1000
chunkIntervalMs: 8000
pushScheduler:
url:
replicaUrls: # array
messageCache:
redis:
url:
replicaUrls: # array
persistDelayMinutes: 10
messageStore:
driverClass: org.postgresql.Driver
user:
password:
url: # example: jdbc:postgresql://127.0.0.1:5432/messagedb
abuseDatabase:
driverClass: org.postgresql.Driver
user:
password:
url: # example: jdbc:postgresql://127.0.0.1:5432/abusedb
testDevices: # array: [ { "number" => "", "code" => "" }, { "number" => "", "code" => "" }, ... ]
maxDevices: # array: [ { "number" => "", "count" => "" }, { "number" => "", "count" => "" }, ... ]
keysDatabase:
driverClass: org.postgresql.Driver
user:
password:
url: # example: jdbc:postgresql://127.0.0.1:5432/keysdb
accountsDatabase:
driverClass: org.postgresql.Driver
user:
password:
url: # example: jdbc:postgresql://127.0.0.1:5432/accountdb
read_database:
driverClass: org.postgresql.Driver
user:
password:
url: # example: jdbc:postgresql://127.0.0.1:5432/readdb
#limits: #use default values in source code
#httpClient: #use default values in source code
#webSocket: #use default values in source code
turn:
secret:
uris: # array
gcm:
senderId:
apiKey:
apn:
pushCertificate:
pushKey:
bundleId:
sandbox: false
unidentifiedDelivery:
certificate:
privateKey:
expiresDays:
voiceVerification:
url:
locales: # array
recaptcha:
secret:
storageService:
userAuthenticationTokenSharedSecret: # hex string
backupService:
userAuthenticationTokenSharedSecret: # hex string
transparentDataIndex: # Map<String, String>
#server: #use default values in source code
#logging: #use default values in source code
#metrics: #use default values in source code
Fill in the various fields of this config.yml again. Don't be too happy too early, it still won't run because some fields have strict requirements that are required in the code through Java annotations. At the beginning, it must have been taken for granted to fill in according to one's own literal understanding, which cannot meet the requirements.
For example, the configuration item 'testDevices' is written in WhisperServerConfiguration. java as follows:
@Valid
@NotNull
@JsonProperty
private List<TestDeviceConfiguration> testDevices = new LinkedList<>();
Note that testDevices is in JSON format, and the code directly gives new an empty set as the default value, which can be left unconfigured. However, if you configure this option in the yml file, it must have a value, which means it must be assigned at least one {number, code} pair. So it's better to comment it out in yml. Configuration items such as maxDevices are also similar. So why is it important to pay attention to Java annotations and corresponding usage code when sorting out these fields at the beginning.
For example, in the userAuthenticationTokenSharedSecret field under storageService and backupService, the parsing code is as follows. Obviously, this is a field in hexadecimal string format and cannot be an empty string.
@NotEmpty
@JsonProperty
private String userAuthenticationTokenSharedSecret;
public byte[] getUserAuthenticationTokenSharedSecret() throws DecoderException {
return Hex.decodeHex(userAuthenticationTokenSharedSecret.toCharArray());
Configure APN certificate - ios push
A slightly more troublesome configuration is the APN certificate. First, you need to apply for a certificate file using an Apple Developer account, convert the certificate file to PEM format, and then paste the string from the PEM file into the yml file. Note that the path to the PEM file is not configured in yml. Why? Read The F * cking Code! The code directly reads the content of the PEM string instead of reading the PEM file, unless the code is changed to read from the PEM file (someone has already done so in the comments on the 1.88 installation guide post).
1:aps.cer
2:push-pro.p12
1、Convert APN certificate to PEM format:
openssl x509 -in aps.cer -inform der -out aps.pem
2、Convert APN private key to PEM format:
Enter the password for the. p12 file, and then set a PEM password to convert to PEM format:
openssl pkcs12 -nocerts -out push-pro.pem -in push-pro.p12
Enter the PEM password set in the previous step and remove the password:
openssl rsa -in push-pro.pem -out push-pro-key-noenc.pem
edit config.yml:
apn:
pushCertificate: |
-----BEGIN CERTIFICATE-----
MIIGCDCCBPCgAwIBAgIId9kHAiU6ZxIwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV
...
...
mYm1yVxw4lLirPPyva9YOqX626RzyKQ0mcOiV0vURjALRiAkNklfpgr877wilvdS
dynVUqLbErSibtAh
-----END CERTIFICATE-----
Configure the key for Sealed Sender
More troublesome is the configuration of the unidentifiedDelivery feature. This function is also known as Sealed Sender, which means anonymous chat messages are sent. Design reference for functions https://signal.org/blog/sealed-sender/ . This feature requires certificate and private key privateKey, but it is not in standard formats such as PEM. Still flipping through the relevant parsing code, you will find that Signal Server comes with command line parameters to generate this data. The specific code can be found in the file service/src/main/java/org/whistlersystems/textsecuregcm/workers/CertificateCommand. java. From this code, it can be seen that there are two steps required.
Step 1: Generate the CA certificate and private key. This CA certificate (note that it is not the private key of the CA) may also be used in the Signal client, and the client can access the server through HTTPS proxy.
java -jar target/TextSecureServer-3.21.jar certificate --ca
Step 2: Use the private key of the CA to generate the server's certificate。
java -jar target/TextSecureServer-3.21.jar certificate --key XXX --id NNNN
XXX is the private key of CA, and NNNN is a numerical number determined by oneself.
java -jar target/TextSecureServer-3.21.jar certificate --ca
Public key : BVttrBH0mkQ5QVh2BX1CMbCyTNdHANg6BVjo+RxDgJgX
Private key: 0MFfk96SBom3rYAU7p861yz/gZCbgXjeYAfWDSL6LW8=
ubuntu@ip-172-31-33-23:~/Signal-Server/service$ java -jar target/TextSecureServer-3.21.jar certificate --key 0MFfk96SBom3rYAU7p861yz/gZCbgXjeYAfWDSL6LW8= --id 1
Certificate: CiUIARIhBdRco3McNmr8yy1UIrX3fFqPqBv3CxqC0IJObRB7SKgZEkB+vzBUqH1I6O+SKZSqDllFLkj/DA2qYuqXWvF+KSLSKMIq3xVAciHBtpGOLE19fmJHHIukUVSp0MIPK7y4l24A
Private key: AIvy5XjaaWiuQgN1omJ/v18DrG9bpBePC5jEei6HWlc=
The final configuration file config.yml
The final content of config.yml obtained. With this configuration, only the initial registration of the mobile client can be completed, and many other functions still need to be tested. The Signal client also has some configurations to modify. Let's get here first, no further ado.
twilio:
accountId: ACf1111111111111111111111111111
accountToken: 3e22222222222222222222222222
numbers:
- +1923456789
localDomain: www.youerdomain.com
messagingServicesId: MG3333333333333333333333333333
push:
queueSize: 200
attachments:
accessKey: AKIAAAAAABBBBBCCCCCCC
accessSecret: QhABCCCCCCCCCCCCCDDDDDDDDDDDDDDDD
bucket: fake
region: ap-southeast-1
cdn:
accessKey: AKIAAAAAABBBBBCCCCCCC
accessSecret: QhABCCCCCCCCCCCCCDDDDDDDDDDDDDDDD
bucket: fake
region: ap-southeast-1
cache:
url: http://127.0.0.1:6379
replicaUrls: [ "http://127.0.0.1:6379" ]
directory:
redis:
url: http://127.0.0.1:6379
replicaUrls: [ "http://127.0.0.1:6379" ]
sqs:
accessKey: AKIAAAAAABBBBBCCCCCCC
accessSecret: QhABCCCCCCCCCCCCCDDDDDDDDDDDDDDDD
queueUrl: https://sqs.ap-southeast-1.amazonaws.com/17093374723/fake
region: ap-southeast-1
client:
userAuthenticationTokenSharedSecret: 33445566 #fake
userAuthenticationTokenUserIdSecret: 22117788 #fake
server:
replicationUrl: http://127.0.0.1 #fake
replicationPassword: fake
replicationCaCertificate: | #fake
-----BEGIN CERTIFICATE-----
MIIGCDCCBPCgAwIBAgIId9kHAiU6ZxIwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV
mYm1yVxw4lLirPPyva9YOqX626RzyKQ0mcOiV0vURjALRiAkNklfpgr877wilvdS
dynVUqLbErSibtAh
-----END CERTIFICATE-----
accountDatabaseCrawler:
chunkSize: 1000
chunkIntervalMs: 80000000
pushScheduler:
url: http://127.0.0.1:6379
replicaUrls: [ "http://127.0.0.1:6379" ]
messageCache:
redis:
url: http://127.0.0.1:6379
replicaUrls: [ "http://127.0.0.1:6379" ]
persistDelayMinutes: 10
messageStore:
driverClass: org.postgresql.Driver
user: signal
password: password
url: jdbc:postgresql://127.0.0.1:5432/messagedb
abuseDatabase:
driverClass: org.postgresql.Driver
user: signal
password: password
url: jdbc:postgresql://127.0.0.1:5432/abusedb
keysDatabase:
driverClass: org.postgresql.Driver
user: signal
password: password
url: jdbc:postgresql://127.0.0.1:5432/keysdb
accountsDatabase:
driverClass: org.postgresql.Driver
user: signal
password: password
url: jdbc:postgresql://127.0.0.1:5432/accountdb
read_database:
driverClass: org.postgresql.Driver
user: signal
password: password
url: jdbc:postgresql://127.0.0.1:5432/readdb
#limits: #use default values in source code
#httpClient: #use default values in source code
#webSocket: #use default values in source code
#viedo call
turn:
secret: turn
uris:
- turn:127.0.0.1:3478?transport=udp
gcm:
senderId: 71722022434122
apiKey: AAAfffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaakkkkkkkkkkkkkkkkeeeeeeeeeeeee
apn:
bundleId: fake
pushCertificate: |
-----BEGIN CERTIFICATE-----
MIIGCDCCBPCgAwIBAgIId9kHAiU6ZxIwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV
mYm1yVxw4lLirPPyva9YOqX626RzyKQ0mcOiV0vURjALRiAkNklfpgr877wilvdS
dynVUqLbErSibtAh
-----END CERTIFICATE-----
pushKey: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsH9uXZaGp2DZ0sfsSI9ovrv4hI2OjEDbzefv5+ZWy0kVdL/r
2UtkH7KXehd9wueaIaZ5+j9PKy3t6x4GPZE4b/fkuXToCijOsbCfhA==
-----END RSA PRIVATE KEY-----
unidentifiedDelivery:
certificate: |
CiYI5A8SIQUO+IlR4c9wwDNmYkD4RRJAob3q9UG4vwkaV1k9iiBPhAXv5liN85Q8vFwEJawOWxIng6WwXo/hoXNFb/TinsRPlI5XuSfQs23FDUVRVXZggQ== #fake
privateKey: |
iCTXE4i2P1t5Y7Vy7SujSQmFfW1E4= #fake
expiresDays: 365
voiceVerification:
url: http://127.0.0.1 #fake
locales: [ "en-US" ] #fake
recaptcha:
secret: 6LfFFFFFFAAAAAAKKKKKKEEEEEEgJ7kX-pSL
storageService:
userAuthenticationTokenSharedSecret: 112233445566 #fake
backupService:
userAuthenticationTokenSharedSecret: 778899AABBCC #fake
transparentDataIndex: # Map<String, String>
#server: #use default values in source code
#logging: #use default values in source code
#metrics: #use default values in source code
### The issue of mismatched server and client code versions
Finally, there is one more pitfall to note: currently, on GitHub (2020 03 16), the latest code for the Master branch of Signal Server does not match the latest code for the Master branch of iOS client. What about the evidence? It is still through the two major tools of logs and debuggers.
generagte zkParams:
java -jar target/TextSecureServer-3.21.jar zkparams
edit config.yml :
zkConfig:
serverSecret: JyH42NTp10znCdBYdvQw9wGuXTk0zjh1PxwxFPlbOAjp4MYv7Lw5FkCNJyidCjknLr1QPB9MD4SHn1t8VtV3DFYAd16B+vQvtHvwdG6N1yw4axE13fOjnK88412ibz5x+JBjg4DlxIkuTQIvYwNqanG3mBNOwxdVsSIUeJeiuggGN3QiKjXY1ON7AOVdlqBVl2oBsayuQXmPxQd02zGVCMnOkeExqF7n2yZjLKcJVStbSLJUYu6JLkUEayEFEKYIrTEbYXmqJ+LGCgj2yTL0XqdrY8RINIWiW6uNVH2azwFM22tTMUppcI9FbeCjeCtZXi68ZiIz923ghAd1m5PzCSZ2UhcYCJvjJzwAOV6YZl7bUlE6BGkloZPfnc+FH4sAoi79doKTj+FAK4geClr3fPZEh8igLt4QxGEpJrn1bwQLgrJWBqwXZlAYZ31w2IaHauPclyNm5cgA/76S1jvtC24cOSMNisn1LK0qLuSH7ucwPj9tYuKUn0gMe7zZf9Fo9h+Zpu03LHhXl34ECGZt/3c8xMlpHwMDuxyt4vTdJR1FT/IDQL6gJT+gVV+TbOzb+q4E3JjmQqpmOvscr8tvCQqz3340pRiW353GPVRJrPgikM0VEgRL1Pzcg5Nc5lMKpplO/sCEylBGltp3740MtacXzDWMi1CkXpFe0ARqrhedb6NLlwAVkxV+cdYJtJA0UGhR0fuI172mZPhtC/VJDLxQQOOdK+ZQ88bIILDZm9zdek8FEtRk2iXTD4tVKvIJRcnq3pn5RdO21pVmWfKtQ1tNT7l5JqAAUomxjK8aIgygFlv58gAtNpeDa3kVSDsHJHiHy01psIHsaHLvM1TQA7xd/3vHpYFOgLHQGXqcYg2wuWQ1Ld0j9uUM+8yFVEQN4LRY4KeKtnpa/v1o4eNA+uIm/CNXcbXVifS71ch+uA5b/1fBpgBsmS0easpeQZB2PLLEJFtvJbL2ln2Uc6ZrBtpvXGCNEEATIbuJscTlBqMrv9CC21A6iPBRQZAf0WkFmviwr3C06gyJ8tiwriYWSTivH5LgJcIL24F3vUf2J1ke5dO6ZIjJxPm9MEl4YQqnjHESFsuv1BXzQRsn9lvwEZZygL/292ktQqaZ7RovScLM9AgZbNxkjeuhD9dbxIEI8BMyEnTr82yZnXE5MSEJy38gVloVHm4L+PLHJZwcXVQ
serverPublic: bhw5Iw2KyfUsrSou5Ifu5zA+P21i4pSfSAx7vNl/0Wj2H5mm7TcseFeXfgQIZm3/dzzEyWkfAwO7HK3i9N0lHZr4sK9wtOoMifLYsK4mFkk4rx+S4CXCC9uBd71H9idZHuXTumSIycT5vTBJeGEKp4xxEhbLr9QV80EbJ/Zb8BHwEzISdOvzbJmdcTkxIQnLfyBWWhUebgv48sclnBxdVA
enabled: ture
serverPublic base64,edit ios config
serverPublicParamsBase64="Ymh3NUl3Mkt5ZlVzclNvdTVJZnU1ekErUDIxaTRwU2ZTQXg3dk5sLzBXajJINW1tN1Rjc2VGZVhmZ1FJWm0zL2R6ekV5V2tmQXdPN0hLM2k5TjBsSFpyNHNLOXd0T29NaWZMWXNLNG1Ga2s0cngrUzRDWENDOXVCZDcxSDlpZFpIdVhUdW1TSXljVDV2VEJKZUdFS3A0eHhFaGJMcjlRVjgwRWJKL1piOEJId0V6SVNkT3Z6YkptZGNUa3hJUW5MZnlCV1doVWViZ3Y0OHNjbG5CeGRWQQ=="
upgrade zkgoup-java to 0.7.0 ,generate again.
Public: APYNGrlVtwuNGiQSgYK/CduMeLLbPVejvNeS/vATQ9hOfipj8mR94eeS28PCVRXUpSRNMRc0WAjqurHi82XfIX+W4lcDbAljgGucmQYyZ7W5zZsuHSbmH3b77p7nXGP/asSFJoOJXAGi8m2iXhVybpQ0AeyOi36an5E6vSOzzdEy5kMLWKjHdeTJOsCCezA0CAa7eLJA+UXp60liO73wZy4
Private: ACyAUqsm7WRUIWlWPkizJ6xAq0ZjZmlNCnDo28GGifMMCjbOnPZIGsmd2ICN5EqL1BjqO/O9m0otsbLjz8CehwaovbaTOKnbJPaXoTPWkSDH9yPcOnmvj6xdm4DOiB37MVTut6DL9yHVdg7S/XnR2amQ6WoyGRI+MwPCFspVimwHKd4oYHDrKTjCndhZnKx2oQcgXVp05JtJfsIRBrBRNg8PEr6FAcIRWeCG6quLxIqfcuPf3Bdn1AgvQz5II369BZsU5rVKTnwjF6CZmVN8UO++JqaK9kqO9YLP3zpMLB4AEmnezjJ7kHFNQaVwVRm0p9Rt6q42P7UssjavjQXngQzEEMwqHt+K0EJuQcLP6K2OtCw4Ti/fFOZ1sUDFN7DVC/YNGrlVtwuNGiQSgYK/CduMeLLbPVejvNeS/vATQ9hOfipj8mR94eeS28PCVRXUpSRNMRc0WAjqurHi82XfIX+vw1vBwQ3XEK0uHIOtKzCh9QAMrxYJxHIdMjSV5aXIBL4xDBDGUP55J3FtzBn58jEMd8C2cwgfhfJGhcgXxh0A8Ne44mRVHX1jXSdtDQ2b+LSxyGrErI5hPgfImPpF3zqDNt4ddJU8EOv7W5orrnEOb9jCoKdc0lb5SWGthwXTDldR6IeiVdnCn7vQBFei9icAPMQ6O14c/dzZogRNIVEBBLaucQxAeWLjKBYdmleRWhYH6mOOW7nMD7GKBkwS3QAgQyAAqp2pFLsWv2Tn8WdcfieFCMaY/p1DTrP/x3zUCiC3TbjGXd0fi4/kpdW4C6QxS+HjHIEESCGCbnrdlSQKKoYxNSJtu4/NtctgFzxo7anCcfi/o8w2O+yJy5ghdgeW4lcDbAljgGucmQYyZ7W5zZsuHSbmH3b77p7nXGP/asSFJoOJXAGi8m2iXhVybpQ0AeyOi36an5E6vSOzzdEy4MoLOGYEd9irEB1caHrh5kmxUmmYyq4RC6HWu5wjJQvmQwtYqMd15Mk6wIJ7MDQIBrt4skD5RenrSWI7vfBnLg
any question send email to 418982099qq@gmail.com
Top comments (0)