반응형

rsa공개키 생성후 파일로 전달하므로 파일을 변환하여 공개/개인 키 구하는 방법을 알아보자.

 

openssl rsa -text -in public.key -inform DER -pubin

(base) netcanis@netcanis-MacBook-Pro KeyPair % openssl rsa -text -in public.key -inform DER -pubin
RSA Public-Key: (1024 bit)
Modulus:
    00:9f:41:52:c2:d0:82:17:18:29:6e:17:3a:ac:a2:
    1a:8c:de:17:5c:89:c1:15:18:78:90:88:53:03:92:
    7e:36:ab:83:26:7d:f5:4b:37:8e:2e:d9:f3:d9:7e:
    e1:b9:0b:fd:99:c9:f4:67:06:c0:df:9f:29:51:2f:
    2b:40:0b:9d:32:4c:47:38:02:f7:6c:d9:d1:72:b1:
    cb:f1:11:90:18:ca:28:dc:00:e3:f8:ce:a9:f9:b7:
    5b:d1:62:ae:5b:06:f8:b2:40:93:bb:31:c1:3a:63:
    76:82:65:11:76:67:db:8a:5d:76:2b:b0:42:ed:31:
    24:a1:76:4b:cb:53:ed:a8:7b
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfQVLC0IIXGCluFzqsohqM3hdc
icEVGHiQiFMDkn42q4MmffVLN44u2fPZfuG5C/2ZyfRnBsDfnylRLytAC50yTEc4
Avds2dFyscvxEZAYyijcAOP4zqn5t1vRYq5bBviyQJO7McE6Y3aCZRF2Z9uKXXYr
sELtMSShdkvLU+2oewIDAQAB
-----END PUBLIC KEY-----

 

openssl rsa -text -in private.key -inform DER

(base) netcanis@netcanis-MacBook-Pro KeyPair % openssl rsa -text -in private.key -inform DER
RSA Private-Key: (1024 bit, 2 primes)
modulus:
    00:9f:41:52:c2:d0:82:17:18:29:6e:17:3a:ac:a2:
    1a:8c:de:17:5c:89:c1:15:18:78:90:88:53:03:92:
    7e:36:ab:83:26:7d:f5:4b:37:8e:2e:d9:f3:d9:7e:
    e1:b9:0b:fd:99:c9:f4:67:06:c0:df:9f:29:51:2f:
    2b:40:0b:9d:32:4c:47:38:02:f7:6c:d9:d1:72:b1:
    cb:f1:11:90:18:ca:28:dc:00:e3:f8:ce:a9:f9:b7:
    5b:d1:62:ae:5b:06:f8:b2:40:93:bb:31:c1:3a:63:
    76:82:65:11:76:67:db:8a:5d:76:2b:b0:42:ed:31:
    24:a1:76:4b:cb:53:ed:a8:7b
publicExponent: 65537 (0x10001)
privateExponent:
    25:ca:9a:99:20:61:be:99:3d:3b:a2:c7:89:af:ee:
    1c:ff:97:0b:9e:a4:f3:1c:9b:7f:b0:da:02:3f:01:
    34:77:fe:e7:63:7c:92:1c:dc:e0:c1:57:dc:84:ff:
    8b:aa:0c:c4:31:e8:8d:8a:4c:ba:c4:4a:49:b9:a7:
    c9:ca:f7:c2:57:38:df:0a:95:27:da:42:66:b0:55:
    03:75:61:53:42:57:f6:8d:f5:d5:0c:f4:81:a9:6c:
    ae:37:9f:e1:39:02:69:11:ec:55:67:31:08:0b:b8:
    66:aa:19:6c:e5:f0:87:5a:16:c5:12:98:71:df:84:
    6c:e0:1a:ac:9b:b6:96:01
prime1:
    00:e5:8c:be:c1:67:56:95:fa:6b:39:8e:43:12:5b:
    fd:e1:e6:2f:86:cb:12:87:df:6d:19:d3:a7:a9:6c:
    70:c5:6f:11:92:4a:e8:ee:d1:70:0c:5d:82:ca:6c:
    03:e6:2a:7d:ce:49:9b:fd:39:3b:71:4a:9f:75:89:
    18:a9:95:23:4d
prime2:
    00:b1:9b:07:6b:e5:a4:c2:9e:1f:eb:24:98:c1:7e:
    c2:e1:3a:5c:d7:20:c0:4e:02:24:e1:3f:15:1c:0d:
    e2:78:c9:54:7e:86:54:92:e5:88:05:f8:90:6b:3c:
    c5:be:4f:61:b7:c3:c0:88:69:7d:34:f3:16:78:bc:
    2a:ec:23:06:e7
exponent1:
    00:b4:ff:2c:2d:dd:68:85:6b:65:fe:84:f0:d7:da:
    17:2e:76:cc:c4:b0:fc:94:8c:14:3f:88:07:2c:6c:
    e7:e2:95:38:3a:ac:bc:4c:0a:72:1a:1d:e5:91:ec:
    67:8a:a5:b8:7a:de:c9:93:79:fc:27:d1:5a:38:57:
    f8:4d:46:de:05
exponent2:
    00:aa:75:94:a5:e5:fe:40:1b:eb:9e:8f:bd:5c:d9:
    00:c9:92:6e:50:bb:4a:56:94:90:38:ef:86:9f:2a:
    64:56:71:44:fb:3a:8a:29:82:cb:0e:90:06:6c:26:
    23:d4:07:f4:4d:9f:3f:46:ad:98:52:1d:8d:4f:cb:
    a9:96:81:f7:b9
coefficient:
    0a:6e:ee:7a:01:58:9b:40:32:e0:d1:d7:d3:a1:45:
    c2:3b:60:9b:84:41:26:7d:01:bf:ec:db:bb:c9:5e:
    57:34:ef:e1:62:9b:a5:0b:b2:21:88:63:07:e5:ab:
    1d:9e:cf:f4:83:ed:5f:0c:78:6a:62:34:e8:51:f8:
    85:13:d3:7c
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCfQVLC0IIXGCluFzqsohqM3hdcicEVGHiQiFMDkn42q4MmffVL
N44u2fPZfuG5C/2ZyfRnBsDfnylRLytAC50yTEc4Avds2dFyscvxEZAYyijcAOP4
zqn5t1vRYq5bBviyQJO7McE6Y3aCZRF2Z9uKXXYrsELtMSShdkvLU+2oewIDAQAB
AoGAJcqamSBhvpk9O6LHia/uHP+XC56k8xybf7DaAj8BNHf+52N8khzc4MFX3IT/
i6oMxDHojYpMusRKSbmnycr3wlc43wqVJ9pCZrBVA3VhU0JX9o311Qz0galsrjef
4TkCaRHsVWcxCAu4ZqoZbOXwh1oWxRKYcd+EbOAarJu2lgECQQDljL7BZ1aV+ms5
jkMSW/3h5i+GyxKH320Z06epbHDFbxGSSuju0XAMXYLKbAPmKn3OSZv9OTtxSp91
iRiplSNNAkEAsZsHa+Wkwp4f6ySYwX7C4Tpc1yDATgIk4T8VHA3ieMlUfoZUkuWI
BfiQazzFvk9ht8PAiGl9NPMWeLwq7CMG5wJBALT/LC3daIVrZf6E8NfaFy52zMSw
/JSMFD+IByxs5+KVODqsvEwKchod5ZHsZ4qluHreyZN5/CfRWjhX+E1G3gUCQQCq
dZSl5f5AG+uej71c2QDJkm5Qu0pWlJA474afKmRWcUT7OoopgssOkAZsJiPUB/RN
nz9GrZhSHY1Py6mWgfe5AkAKbu56AVibQDLg0dfToUXCO2CbhEEmfQG/7Nu7yV5X
NO/hYpulC7IhiGMH5asdns/0g+1fDHhqYjToUfiFE9N8
-----END RSA PRIVATE KEY-----

 

2020/12/17 - [Android/Java] - RSA 암복호화

2020/12/17 - [iOS/Tips] - URL query 파싱 및 json string 변환

2020/12/16 - [개발노트] - Code 128 Barcode의 Check Digit 계산방법

2020/12/15 - [iOS/Tips] - 디버깅 차단 처리 (Anti Debug)

2020/12/14 - [iOS/Tips] - bundle id 알아내기

2020/12/12 - [AI/Algorithm] - 2D 충돌처리

2020/12/11 - [iOS/Swift] - UIViewController 스위칭

2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)

2020/12/11 - [개발노트] - 특수문자 발음

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

반응형
블로그 이미지

SKY STORY

,

RSA 암복호화

개발/Note 2020. 12. 17. 16:18
반응형

결제 관련 API 연동(VAN, PG, 간편결제 등) 할 경우 RSA암복호화 과정을 거치게되는데

이 부분에 대한 샘플 코드를 작성해 보았다.

 

Apache Commons Codec 다운로드

commons.apache.org/proper/commons-codec/

 

Codec – Home

Apache Commons Codec Apache Commons Codec (TM) software provides implementations of common encoders and decoders such as Base64, Hex, Phonetic and URLs. Impetus Codec was formed as an attempt to focus development effort on one definitive implementation of

commons.apache.org

 

프로젝트 라이브러리에 추가. 

 

PublicKey와 PrivateKey 파일을 생성

package com.ubpay.keypair;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;

//
// RSA Key 파일 생성
//
// Created by netcanis on 2019/04/29.
// Copyright © 2019 netcanis. All rights reserved.
//

// Download Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/download_codec.cgi

public class GenKeys
{
	private KeyPairGenerator keyGen;
	private KeyPair pair;
	private PrivateKey privateKey;
	private PublicKey publicKey;

	// RSA 초기화 및 키 생성 
	public GenKeys(int keysize) throws NoSuchAlgorithmException, NoSuchProviderException {
		this.keyGen = KeyPairGenerator.getInstance("RSA");
		this.keyGen.initialize(keysize);
		this.pair = this.keyGen.generateKeyPair();
		this.publicKey = pair.getPublic();
		this.privateKey = pair.getPrivate();
	}

	public PublicKey getPublicKey() {
		return this.publicKey;
	}
	
	public PrivateKey getPrivateKey() {
		return this.privateKey;
	}
	
	public void writeToFile(String path, byte[] key) throws IOException {
		File f = new File(path);
		f.getParentFile().mkdirs();

		FileOutputStream fos = new FileOutputStream(f);
		fos.write(key);
		fos.flush();
		fos.close();
	}

	
	
	public static void main(String[] args) {
		GenKeys genKeys;
		try {
			// 1024bit key pair 생성  
			genKeys = new GenKeys(1024);
			
			System.out.println(genKeys.publicKey);
			System.out.println(genKeys.privateKey);
			
			// 바이너리 파일로 저장 
			genKeys.writeToFile("KeyPair/public.key", genKeys.getPublicKey().getEncoded());
			genKeys.writeToFile("KeyPair/private.key", genKeys.getPrivateKey().getEncoded());
			
		} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
			System.err.println(e.getMessage());
		} catch (IOException e) {
			System.err.println(e.getMessage());
		}
	}
}

 

생성 결과

 

생성된 키를 이용하여 암복호화 테스트

package com.ubpay.rsaTest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;


//
// RSA 암복호화 및 테스트
//
// Created by netcanis on 2019/04/29.
// Copyright © 2019 netcanis. All rights reserved.
//

public class RSAEncryption
{
	private Cipher cipher;
	
	public RSAEncryption() throws NoSuchAlgorithmException, NoSuchPaddingException{
		this.cipher = Cipher.getInstance("RSA");
	}
	
	// 주어진 파일을 byte array로 읽기 
	public byte[] getFileInBytes(File f) throws IOException{
		FileInputStream fis = new FileInputStream(f);
		byte[] fbytes = new byte[(int) f.length()];
		fis.read(fbytes);
		fis.close();
		return fbytes;
	}
		
	// X509EncodedKey
	public PublicKey getPublic(String filename) throws Exception {
		byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
		X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
		KeyFactory kf = KeyFactory.getInstance("RSA");
		return kf.generatePublic(spec);
	}

	// PKCS8EncodedKeySpec
	public PrivateKey getPrivate(String filename) throws Exception {
		byte[] keyBytes = Files.readAllBytes(new File(filename).toPath());
		
		//byte[] decoded = Base64.getDecoder().decode(keyBytes);
		//println(new String(decoded));    // Outputs "Hello"
		
		//Base64 codec = new Base64();
		//byte[] decoded = codec.decode(keyBytes);
		//System.out.println( new String(decoded) );    // Outputs "Hello"
		
		PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory kf = KeyFactory.getInstance("RSA");
		return kf.generatePrivate(spec);
	}
	
	// public key로 암호화 
	public String encrypt(String str, PublicKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException{
		this.cipher.init(Cipher.ENCRYPT_MODE, key);
		return Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
	}
	
	// private key로 복호화 
	public String decrypt(String str, PrivateKey key) throws InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException{
		this.cipher.init(Cipher.DECRYPT_MODE, key);
		return new String(cipher.doFinal(Base64.decodeBase64(str)), "UTF-8");
	}

	// hex to byte[]
	public byte[] hexStringToByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
	                             + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	// byte[] to hex
	public String byteArrayToHexString(byte[] bytes){ 
		StringBuilder sb = new StringBuilder(); 
		for(byte b : bytes){ 
			sb.append(String.format("%02X", b&0xff)); 
		} 
		return sb.toString(); 
	} 

	
    
	public static void main(String[] args) throws Exception {
		RSAEncryption ac = new RSAEncryption();
		
		// 공개키
		PublicKey publicKey = ac.getPublic("KeyPair/public.key");
		// 개인키 
		PrivateKey privateKey = ac.getPrivate("KeyPair/private.key");
		
		// 원문 
		String msg = "test message";
		
		
		System.out.println("----------------------------------------------------");
		System.out.println(":::: TEST 암호화 및 복호화 ::::");
		
		// 암호화 원문 BASE64
		String encryptedString = ac.encrypt(msg, publicKey);
		// 복호화
		String decryptedString = ac.decrypt(encryptedString, privateKey);
		
		System.out.println("----------------------------------------------------");
		System.out.println(
				"원문 = " + msg + "\n" +
				"공개키 암호화 = " + encryptedString + "\n" +
				"개인키 복호화 = " + decryptedString
				);
		System.out.println("----------------------------------------------------");
	}
}




결과 :
--------------------------------------------------------------------------
:::: TEST 암호화 및 복호화 ::::
--------------------------------------------------------------------------
원문 = test message
공개키 암호화 = gz2WQHCyHxsPV5IB0xehk8RSbGrhGR86nQRGj09CphxiIAjRsCony8myWfRGJgDVyK6ixuK13gtL/20j4K5c1GcCKxPT9xqYaa6tBxTakho9klHNAO6KhQJK0nGeIQRDpZ1qecB6pPMsRqVVO5rb81NFqbjLKMoqi2tO1f55/iM=
개인키 복호화 = test message
--------------------------------------------------------------------------

 

2020/12/17 - [OS/Mac OS X] - OpenSSL을 이용한 Key 정보 Text 변환

2020/12/17 - [iOS/Tips] - URL query 파싱 및 json string 변환

2020/12/16 - [개발노트] - Code 128 Barcode의 Check Digit 계산방법

2020/12/15 - [iOS/Tips] - 디버깅 차단 처리 (Anti Debug)

2020/12/14 - [iOS/Tips] - bundle id 알아내기

2020/12/12 - [AI/Algorithm] - 2D 충돌처리

2020/12/11 - [iOS/Swift] - UIViewController 스위칭

2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)

2020/12/11 - [개발노트] - 특수문자 발음

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

 

반응형
블로그 이미지

SKY STORY

,
반응형

일반적으로 많이 사용되는 Code 128 바코드 체크비트 내용에 대해 알아보자.

CODE 128은 전체 ASCII 128 문자를 모두 표현할 수 있는 연속형 심벌로지이며, 수치 데이터는 심벌 문자당 두 자리로 표현한다. 1981년 Computer Identics Corp. 사에서 개발한 CODE 128은 현재 UPCSKS EAN등 데이터의 고밀도 표현을 요하는 여러 분야에서 응용, 사용되고 있다. CODE 12I9은 시작과 끝 문자, 변동 가능한 길이의 데이터, 바와 스페이스 두 개 모두에 대한 캐릭터 패리티, 체크 문자, 함수 문자 등으로 구성되어 있으며 인쇄가 보다 용이하며 현재 사용되고 있는 각종 컴퓨터, 프린터에 적당하다. 

CODE 128의 심벌 구조는 좌우측 여백으로 인쇄돼지 않는 영역이 있고, 바코드화된 캐릭터의 연속은 단일한 시작 문자로 시작된다. 바로 옆에 가장 중요한 Most Significant가 오고 체크 문자 그리고 단일한 끝 문자가 온다.

CODE 128의 캐릭터 요소는 8개로 구성되며 각 요소들은 바 또는 바의 부분으로 이루어지면 각 캐릭터는 세 개의 바와 스페이스로 이루어진다. 각각의 바는 짝수 모듈(짝수 패리티)이고 스페이스는 홀수 모듈(홀수 패리티)로 이루어진다. 각 요소들의 폭은 1X, 2X, 3X, 4X의 네 가지로 바의 모듈은 '1'로, 여백의 모듈은 '0'으로 표시된다. 시작 문자는 세 종류의 문자 패턴(A, B, C)이 있으며 끝 문자는 네 개의 바와 세 개의 스페이스, 여기에 두 개의 모듈과 종료 바(2)가 합쳐져 13개의 모듈(13X)로 구성된다. 

CODE 128의 코드 구조는 A, B, C  가지 문자 집합이 있는데 심벌 시작문자가 A로 시작되면 코드 A의 집합으로 정의된다. 심벌의 중간에 전이 문자(shift character)를 사용해 다른 문자 집합으로 옮길 수 있다. 문자 집합 A는 모든 alphanumeric 문자의 특수 문자, 컨트롤 문자를 포함하며 문자 집합 B는 모든 alphanumeric 문자와 특수 문자, 컨트롤 문자를 포함하는데 alphanumeric 문자들의 낮은 경우가 포함된다. 문자 집합 C는 00에서 99까지의 디지트쌍 100개와 특수 문자를 갖는데 문자마다 두 자리를 수치로 표현하므로 데이터의 밀도가 두 배이다. CODE 128에는 문자 집합 선택 문자(A, B, C), 전이 문자, 기능 문자가 모두 특수 문자로 존재하며, 한 개의 심벌 안에서 또는 한 개의 코드 부분 집합에서 다른 코드의 부분 집합으로 변화가 가능하다. 

Code 128 3개의 각각 폭이 다른 검은 바와 흰 바가 조합되어 문자를 표시하는 1차원 바코드. 1981년 컴퓨터 아 이덴틱스사가 개발하였다. 문자 1개는 11 모듈로 구성되어있다. 모든 ASCII 문자를 지원하며 128∼255 범위의 문자도 입력 가능하다.7) Code 128 심벌 폭의 최소화를 위해 동일한 문자를 서로 다른 코드 세 트(코드 세트 A, B, C)의 조합을 통하여 표현하는 알고리즘을 가지고 있다. 심벌의 길이는 정해져 있지 않지만 판독기의 용량을 감안하면 최대 약 48개 문자로 된 데이터를 저장할 수 있다.

참고 원문 :
https://en.wikipedia.org/wiki/Code_128

https://courses.cs.washington.edu/courses/cse370/01au/minirproject/ModusPeons/index.htm

https://www.adams1.com/128code.html

https://www.adams1.com/128table.html

 

Code 128 Structure

 

 

  • Left Quiet Zone
  • Start character 
  • Data characters: any length
  • Checksum: one checksum in modulo 103
  • Stop character 
  • Termination bar
  • Right Quiet Zone

In ISO/IEC 15417 specification, the quiet zone should be at least ten times the width of the narrowest bar/space element. It is mandatory at the left and right side of the barcode.

 

Code 128 Encodable Character Set

  • Code 128 A (Code Set A): 0-9, A-Z, and special characters
  • Code 128 B (Code Set B): 0-9, A-Z, a-z, and special characters
  • Code 128 C (Code Set C): numeric digit pairs 00-99 and three special characters

 

Code 128 Barcode Table Of Characters
(For the complete Code 128 specification, see the Code 128 Page)

The table below shows the three different character sets along with the decimal values of each character, which is used in calculating the Check Character. The final column shows the bar/space pattern for the character. The numbers indicate the number of modules wide the given space or bar is. To get the extended ASCII decimal, add 32 to the decimal value in the first column. There is a nice extended ASCII table here. Please note that Code 128 can only encode the English alphabet.

Value

Code A

Code B

Code C

Pattern

B S B S B S

What ASCII Code Do I Print?

0

SP

SP

00

2 1 2 2 2 2

SP (ASCII 32)

1

!

!

01

2 2 2 1 2 2

! (ASCII 33)

2

"

"

02

2 2 2 2 2 1

" (ASCII 34)

3

#

#

03

1 2 1 2 2 3

# (ASCII 35)

4

$

$

04

1 2 1 3 2 2

$ (ASCII 36)

5

%

%

05

1 3 1 2 2 2

% (ASCII 37)

6

&

&

06

1 2 2 2 1 3

& (ASCII 38)

7

'

'

07

1 2 2 3 1 2

' (ASCII 39)

8

(

(

08

1 3 2 2 1 2

( (ASCII 40)

9

)

)

09

2 2 1 2 1 3

) (ASCII 41)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

10

*

*

10

2 2 1 3 1 2

* (ASCII 42)

11

+

+

11

2 3 1 2 1 2

+ (ASCII 43)

12

,

,

12

1 1 2 2 3 2

, (ASCII 44)

13

-

-

13

1 2 2 1 3 2

- (ASCII 45)

14

.

.

14

1 2 2 2 3 1

. (ASCII 46)

15

/

/

15

1 1 3 2 2 2

/ (ASCII 47)

16

0

0

16

1 2 3 1 2 2

0 (ASCII 48)

17

1

1

17

1 2 3 2 2 1

1(ASCII 49)

18

2

2

18

2 2 3 2 1 1

2 (ASCII 50)

19

3

3

19

2 2 1 1 3 2

3 (ASCII 51)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

20

4

4

20

2 2 1 2 3 1

4 (ASCII 52)

21

5

5

21

2 1 3 2 1 2

5 (ASCII 53)

22

6

6

22

2 2 3 1 1 2

6 (ASCII 54)

23

7

7

23

3 1 2 1 3 1

7 (ASCII 55)

24

8

8

24

3 1 1 2 2 2

8 (ASCII 56)

25

9

9

25

3 2 1 1 2 2

9 (ASCII 57)

26

:

:

26

3 2 1 2 2 1

: (ASCII 58)

27

;

;

27

3 1 2 2 1 2

; (ASCII 59)

28

<

<

28

3 2 2 1 1 2

< (ASCII 60)

29

=

=

29

3 2 2 2 1 1

= (ASCII 61)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

30

>

>

30

2 1 2 1 2 3

> (ASCII 62)

31

?

?

31

2 1 2 3 2 1

? (ASCII 63)

32

@

@

32

2 3 2 1 2 1

@ (ASCII 64)

33

A

A

33

1 1 1 3 2 3

A (ASCII 65)

34

B

B

34

1 3 1 1 2 3

B (ASCII 66)

35

C

C

35

1 3 1 3 2 1

C (ASCII 67)

36

D

D

36

1 1 2 3 1 3

D (ASCII 68)

37

E

E

37

1 3 2 1 1 3

E (ASCII 69)

38

F

F

38

1 3 2 3 1 1

F (ASCII 70)

39

G

G

39

2 1 1 3 1 3

G (ASCII 71)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

40

H

H

40

2 3 1 1 1 3

H (ASCII 72)

41

I

I

41

2 3 1 3 1 1

I (ASCII 73)

42

J

J

42

1 1 2 1 3 3

J (ASCII 74)

43

K

K

43

1 1 2 3 3 1

K (ASCII 75)

44

L

L

44

1 3 2 1 3 1

L (ASCII 76)

45

M

M

45

1 1 3 1 2 3

M (ASCII 77)

46

N

N

46

1 1 3 3 2 1

N (ASCII 78)

47

O

O

47

1 3 3 1 2 1

O (ASCII 79)

48

P

P

48

3 1 3 1 2 1

P (ASCII 80)

49

Q

Q

49

2 1 1 3 3 1

Q (ASCII 81)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

50

R

R

50

2 3 1 1 3 1

R (ASCII 82)

51

S

S

51

2 1 3 1 1 3

S (ASCII 83)

52

T

T

52

2 1 3 3 1 1

T (ASCII 84)

53

U

U

53

2 1 3 1 3 1

U (ASCII 85)

54

V

V

54

3 1 1 1 2 3

V (ASCII 86)

55

W

W

55

3 1 1 3 2 1

W (ASCII 87)

56

X

X

56

3 3 1 1 2 1

X (ASCII 88)

57

Y

Y

57

3 1 2 1 1 3

Y (ASCII 89)

58

Z

Z

58

3 1 2 3 1 1

Z (ASCII 90)

59

[

[

59

3 3 2 1 1 1

[ (ASCII 91)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

60

\

\

60

3 1 4 1 1 1

\ (ASCII 92)

61

]

]

61

2 2 1 4 1 1

] (ASCII 93)

62

^

^

62

4 3 1 1 1 1

^ (ASCII 94)

63

_

_

63

1 1 1 2 2 4

_ (ASCII 95)

64

NUL

'

64

1 1 1 4 2 2

` (ASCII 96)

65

SOH

a

65

1 2 1 1 2 4

a (ASCII 97)

66

STX

b

66

1 2 1 4 2 1

b (ASCII 98)

67

ETX

c

67

1 4 1 1 2 2

c (ASCII 99)

68

EOT

d

68

1 4 1 2 2 1

d (ASCII 100)

69

ENQ

e

69

1 1 2 2 1 4

e (ASCII 101)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

70

ACK

f

70

1 1 2 4 1 2

f (ASCII 102)

71

BEL

g

71

1 2 2 1 1 4

g (ASCII 103)

72

BS

h

72

1 2 2 4 1 1

h (ASCII 104)

73

HT

i

73

1 4 2 1 1 2

i (ASCII 105)

74

LF

j

74

1 4 2 2 1 1

j (ASCII 106)

75

VT

k

75

2 4 1 2 1 1

k (ASCII 107)

76

FF

l

76

2 2 1 1 1 4

l (ASCII 108)

77

CR

m

77

4 1 3 1 1 1

m (ASCII 109)

78

SO

n

78

2 4 1 1 1 2

n (ASCII 110)

79

SI

o

79

1 3 4 1 1 1

o (ASCII 111)

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

80

DLE

p

80

1 1 1 2 4 2

p (ASCII 112)

81

DC1

q

81

1 2 1 1 4 2

q (ASCII 113)

82

DC2

r

82

1 2 1 2 4 1

r (ASCII 114)

83

DC3

s

83

1 1 4 2 1 2

s (ASCII 115)

84

DC4

t

84

1 2 4 1 1 2

t (ASCII 116)

85

NAK

u

85

1 2 4 2 1 1

u (ASCII 117)

86

SYN

v

86

4 1 1 2 1 2

v (ASCII 118)

87

ETB

w

87

4 2 1 1 1 2

w (ASCII 119)

88

CAN

x

88

4 2 1 2 1 1

x (ASCII 120)

89

EM

y

89

2 1 2 1 4 1

y (ASCII 121

Value

Code A

Code B

Code C

Pattern

B S B S B S

 

90

SUB

z

90

2 1 4 1 2 1

z (ASCII 122)

91

ESC

{

91

4 1 2 1 2 1

{ (ASCII 123)

92

FS

|

92

1 1 1 1 4 3

| (ASCII 124)

93

GS

}

93

1 1 1 3 4 1

} (ASCII 125)

94

RS

~

94

1 3 1 1 4 1

~ (ASCII 126)

95 (Hex 7F)

US

DEL

95

1 1 4 1 1 3

DEL (ASCII 127)

96 (Hex 80)

FNC 3

FNC 3

96

1 1 4 3 1 1

Ç (ASCII 128)

97 (Hex 81)

FNC 2

FNC 2

97

4 1 1 1 1 3

ü (ASCII 129)

98 (Hex 82)

SHIFT

SHIFT

98

4 1 1 3 1 1

é (ASCII 130)

99 (Hex 83)

CODE C

CODE C

99

1 1 3 1 4 1

â (ASCII 131)

100 (Hex 84)

CODE B

FNC 4

CODE B

1 1 4 1 3 1

ä (ASCII 132)

101 (Hex 85)

FNC 4

CODE A

CODE A

3 1 1 1 4 1

à (ASCII 133)

102 (Hex 86)

FNC 1

FNC 1

FNC 1

4 1 1 1 3 1

å (ASCII 134)

 

Value

Start Code

Pattern

B S B S B S

What ASCII Code Do I Print?

103 (Hex 87)

START (Code A)

2 1 1 4 1 2

‡ (ASCII 135)

104 (Hex 88)

START (Code B)

2 1 1 2 1 4

ˆ (ASCII 136)

105 (Hex 89)

START (Code C)

2 1 1 2 3 2

‰ (ASCII 137)

106 (Hex 6A)

STOP (All Codes)

2 3 3 1 1 1 2

Š (ASCII 138)

 

 

Check Digit 계산 방법

ex) "BarCode 1" 에 대한 Code 128 Check Digit계산방법.
시작 코드셋이 START B일 경우 (START A:103, START B: 104, START C: 105)

START B = 104
B = 66 - 32 = 34
a = 97 - 32 = 65
r = 114 - 32 = 82
C = 67 - 32 = 35
o = 111 - 32 = 79
d = 100 - 32 = 68
e = 101 - 32 = 69
   = 32 - 32 = 0
1  = 49 - 32 = 17

// 아래와 같이 자리수 별로 곱을한 값들을 모두 더하고 시작 코드셋 값으로 나눈 나머지 값이 Check Digit이 된다.
Total = 104 + (34x1) + (65x2) + (82x3) + (35x4) + (79x5) + (68x6) + (69x7) + (0x8) + (17x9) = 2093
Check Digit = 2093 mod 104 = 33(A)
                   = 33 + 32 = 65 = 'A' // 최종 출력 값은 32를 더한 값인 65('A')를 출력.

Final message : (START B)BarCode 1(A)(STOP)

 

2020/12/15 - [iOS/Tips] - 디버깅 차단 처리 (Anti Debug)

2020/12/14 - [iOS/Tips] - bundle id 알아내기

2020/12/12 - [AI/Algorithm] - 2D 충돌처리

2020/12/11 - [iOS/Swift] - UIViewController 스위칭

2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)

2020/12/11 - [개발노트] - 특수문자 발음

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

 

 

반응형

'개발 > Note' 카테고리의 다른 글

OpenSSL을 이용한 Key 정보 Text 변환  (0) 2020.12.17
RSA 암복호화  (0) 2020.12.17
PlantUML 설치 (Mac OS X)  (0) 2020.12.11
특수문자 발음  (0) 2020.12.11
Bluetooth UUID  (0) 2020.12.10
블로그 이미지

SKY STORY

,
반응형

시퀀스다이어그램 작업시 자주 사용 중인데 Visual Studio Code에서 사용 중입니다.

물론 플러그인으로 제공되므로 현재 작업중이신 개발툴에 설치 가능합니다.

 

Visual Studio Code 설치
https://code.visualstudio.com/download

Extensions 메뉴 선택 후 ‘PlantUML’ 검색 및 설치

plantuml.jar 다운로드 
https://sourceforge.net/projects/plantuml/files/plantuml.jar/download

brew 설치
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ install/master/install)"

java 설치
brew cask install java

plantuml.jar 파일 로컬 폴더에 복사
mkdir -p /usr/local/Cellar/plantuml && cp ~/Downloads/plantuml.jar /usr/local/ Cellar/plantuml

Graphviz 설치 
http://www.graphviz.org/download/ 
brew install graphviz

숨겨진 파일 보이기
Ctrl + Shift + .

sudo ln -s /usr/local/Cellar/plantuml /usr/local/bin/plantuml

~/.zshrc 파일에 환경 설정
# Add environment variable JAVA_HOME
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/Contents/ Home
export PATH=$JAVA_HOME:$PATH

# Add environment variable PLANTUML_JAR
export PLANTUML_JAR=/usr/local/Cellar/plantuml/plantuml.jar export PATH=$PLANTUML_JAR:$PATH

# Add environment variable GRAPHVIZ_DOT export GRAPHVIZ_DOT=/usr/local/bin/dot export PATH=$GRAPHVIZ_DOT:$PATH

 

콘솔창 재실행 후 환경설정 재로드
source ~/.zshrc

저장방법 :
Command + Shift + P
PlantUML: Export Current File Diagram 
선택 png 또는 svg를 선택

 

참고자료 :

가이드 문서 : http://plantuml.com/ko/guide

Apple fonts 다운로드 : https://developer.apple.com/fonts/

 

 

2020/12/16 - [개발노트] - Code 128 Barcode의 Check Digit 계산방법

2020/12/15 - [iOS/Tips] - 디버깅 차단 처리 (Anti Debug)

2020/12/14 - [iOS/Tips] - bundle id 알아내기

2020/12/12 - [AI/Algorithm] - 2D 충돌처리

2020/12/11 - [iOS/Swift] - UIViewController 스위칭

2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)

2020/12/11 - [개발노트] - 특수문자 발음

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

 

반응형

'개발 > Note' 카테고리의 다른 글

RSA 암복호화  (0) 2020.12.17
Code 128 Barcode의 Check Digit 계산방법  (0) 2020.12.16
특수문자 발음  (0) 2020.12.11
Bluetooth UUID  (0) 2020.12.10
모바일 앱 메모리덤프 이슈 해결방법  (0) 2020.12.08
블로그 이미지

SKY STORY

,

특수문자 발음

개발/Note 2020. 12. 11. 09:53
반응형

별것 아니지만 중요한 것이죠. 정리해 봅니다.

The english name of special characters

# = pound sign (American English), hash sign (British English)

£ = pound sign (British English)

@ = at sign

$ = dollar sign

% = percent sign

^ = caret [kǽrit]

& = ampersand [ǽmpərsӕnd]

* = asterisk [ǽstərìsk]

~ = tilde [tíldə]

! = exclamation mark [èkskləméiʃən][maːrk]

() = parentheses [pərénðiziz]  -  parenthesis [pərénθisis]

- = hyphen [háifən]

_ = underscore [Λndərskɔ̀ːr---´]

+ = plus sign

= = equals sign

[] = square brackets[brǽkit]

{} = curly brackets (is there something more "official"? braces?)

\ = backslash

/ = slash, solidus  [slæʃ], [sάlidəs]

<> = angle brackets

¶ = paragraph mark, pilcrow sign [pǽrəgrӕf] [pílkrou]

§ = section sign

= copyright sign

= Yen sign [jen]

= cent sign

º = degree symbol, ordinal indicator

× = multiplication sign [mΛltəplikéiʃən] 

÷ = division sign

 

반응형
블로그 이미지

SKY STORY

,

Bluetooth UUID

개발/Note 2020. 12. 10. 13:31
반응형

블루투스의 UUID

  • 범용 고유 번호(Universally Unique IDentifiers) 라고 불리며, 128 비트의 숫자들을 조합한다.
  • 범용적으로 사용할 수 있는 고유의 ID를 사용하기 위해 생성되며, 그렇기 때문에 128 비트의 HEX 조합 unique 하여야 한다.
  • Bluetooth 에서는 device에서 제공하는 service를 검색하여 각 service 마다 UUID 를 부여하는등 많은 부분에서 사용된다.

 

UUID의 구성 요소

[time low] - [time mid] - [time high and version] - [clock seq_hi and reserved] - [clock seq low node]

ex) 000011001-0000-1000-8000-00805F9B34FB

  • time low : 타임 스탬프(시간표시) 의 최하위 32 비트.
  • 블루투스 device 끼리 통신을 하기 위해서 소켓 생성시 UUID 가 필요한데 이는 해당 프로토콜의 의미 한다.
  • 안드로이드 플랫폼의 단말기끼리는 어떤 UUID를 사용하여도 되지만 특정 프로토콜의 device에 접근하 기 위해서는 각각의 프로토콜 UUID 를 사용하여만 한다.

 

 

반응형
블로그 이미지

SKY STORY

,
반응형

메모리 덤프를 해결하는 방법에 대해 간단히 팁을 알려드립니다.

메모리 덤프는 실시간이 아니라 특정 시점에 사용중인 메모리를 덤프 하는 것입니다.

그렇기 때문에 메모리를 사용하고나서 바로 사용한 메모리 공간을 초기화 시켜주면 덤프 시 해당 메모리 내용을 볼 수 없게 됩니다.

하지만 현실은 그렇게 쉽지 않죠.. c/c++로 직접 메모리를 제어할 경우 사용한 메모리 초기화하고 제거하면 되겠지만 언어 자체가 메모리를 알아서 관리해 주다보니 제어하기 쉽지 않죠.

해결 방법은 메모리를 생성하여 해당 메모리 내용을 치환하면 됩니다.

예를들어 메모리 버퍼를 생성하고 "ABC12"라는 내용이 할당하였다고 할때 다음과 같이 특수문자로 치환합니다.

'A'->'{', 'B'->'}', 'C'-'>', '1'->'[', '2'->']'

해당 메모리 사용 후 생성된 버퍼를 '0'으로 모두 채워주면 덤프로 해당 내용이 특수문자로 나오거나 빈값으로 처리 됩니다.

물론 원본 데이터를 사용해야 할 경우 로컬 변수로 버퍼를 생성하고 치환된 데이터를 메모리 카피하여

다시 정해진 룰에 따라 치환하여 원본 데이터를 사용하고 생성된 로컬변수는 다시 '0'으로 채워줍니다.

재밌게도 메모리에 다른값을 할당하지 않고 replace 함수로 치환하게 되면 딥 메모리 카피가 일어나지 않고

해당 메모리 실제 데이터 값만 변경이 이루어져 덤프 이슈를 해결할 수 있습니다.

 

2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동

2020/08/21 - [Android/Tips] - aab파일 apk파일로 변환

2020/08/11 - [iOS/Swift] - WKWebView 화면 출력 완료 이벤트

2020/08/06 - [iOS/Tips] - 개발관련 폴더 경로

2020/07/19 - [Android/Tips] - 안드로이드 원격 디버깅 방법

2020/07/18 - [Android/Tips] - Cannot convert string value 'JETPACK_COMPOSE' to an enum value of type 'com.android.builder.model.AndroidGradlePluginProjectFlags$BooleanFlag' (valid case insensitive values: APPLICATION_R_CLASS_CONSTANT_IDS, TEST_R_CLASS_CONSTANT_IDS, TRANSITIVE_R_CLASS)

2020/07/18 - [Android/Tips] - OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

2020/07/17 - [iOS/Tips] - 웹에서 iOS 앱 설치여부 체크

2020/07/14 - [Android/Tips] - 웹에서 안드로이드 앱을 실행 (Custom URL Scheme)

2020/07/11 - [OS/Mac OS X] - SMC(System Management Controller) 재설정

2020/07/11 - [OS/Mac OS X] - NVRAM(PRAM) 재설정 방법

2020/07/11 - [iOS/Swift] - Dictionary sort

2020/07/11 - [iOS/Swift] - UTC시간, Locale시간 변경

2020/07/11 - [iOS/Swift] - SEED 블록암호 알고리즘 CBC (Cipher Block Chaining) 예제2

반응형

'개발 > Note' 카테고리의 다른 글

특수문자 발음  (0) 2020.12.11
Bluetooth UUID  (0) 2020.12.10
Android, iOS 앱 설치여부 체크 및 스토어 이동  (0) 2020.12.08
SMC(System Management Controller) 재설정  (0) 2020.07.11
NVRAM(PRAM) 재설정 방법  (0) 2020.07.11
블로그 이미지

SKY STORY

,
반응형

스마트폰 BTC 채굴앱
https://get.cryptobrowser.site/34473645

 

Earn coins while browsing the web

Earn bitcoins while watching videos, chatting, or playing online. It has never been so easy to increase your income! Tell your friends about CryptoTab Browser, invite them to join, and earn more together. Grow your network—get more profit!

get.cryptobrowser.site

 

모바일 웹 페이지에서 스마트폰의 특정앱이 설치되어 있을 경우 앱을 실행하고
그렇지 않으면 스토어로 이동 시켜야 하는 경우 다음과 같이 처리하여 해결할 수 있다.

 

Android :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.mytest.mypackageid">
	...
</manifest>

<application>
	....
	<activity
		...
		<intent-filter>
			...
			<data android:host="action" android:scheme="myScheme" />
		</intent-filter>
	</activity>
    ....
</application>
방법 1:
location.href = "Intent://action#Intent;scheme=myscheme;package=com.mytest.mypackageid;end";

방법 2:
location.href = "https://play.google.com/store/apps/details?id=com.mytest.mypackageid";

 

참고 자료 :

https://developer.chrome.com/multidevice/android/intents

 

Android Intents with Chrome - Google Chrome

Chrome Extend the Browser What are Extensions? Get Started Tutorial Overview Manifest Format Manage Events Design User Interface Content Scripts Declare Permissions and Warn Users Give Users Options Developer Guide Reach Peak Performance Protect User Priva

developer.chrome.com

 

iOS :

//
// 방법 1 : Timer 이용한 방법
//
function openAppOrStore() {
	var timeout = setTimeout(function () { 
    	window.location = "https://itunes.apple.com/app/id123456789"; 
	}, 25);
	window.location = "myappscheme://";
	clearTimeout(timeout);
}

//
// 방법 2 : iframe을 이용한 방법
//
function openAppOrStore() {
  var appURL = "yourappname://";
  var appStoreURL = "https://itunes.apple.com/app/yourappname/id1234567890";
  
  // 앱이 설치되어 있는지 확인
  var iframe = document.createElement("iframe");
  iframe.style.display = "none";
  iframe.src = appURL;
  document.body.appendChild(iframe);
  
  setTimeout(function() {
    document.body.removeChild(iframe);
    // 앱이 설치되어 있다면 앱 실행
    window.location.href = appURL;
  }, 2000);
  
  // 앱이 설치되어 있지 않다면 앱스토어 다운로드 페이지로 이동
  setTimeout(function() {
    window.location.href = appStoreURL;
  }, 4000);
}
위 코드에서는 `yourappname://`이라는 URL Scheme을 이용하여 앱이 설치되어 있는지를 확인합니다. 
만약 앱이 설치되어 있다면 해당 URL Scheme을 가진 앱을 실행하게 됩니다. 
반면, 앱이 설치되어 있지 않다면 `https://itunes.apple.com/app/yourappname/id1234567890`와 같은 
링크를 이용하여 앱스토어 다운로드 페이지로 이동시킵니다. 
이 때, `window.location.href`를 변경하여 앱스토어 페이지로 이동합니다.



//
// 방법 3 : 'canOpenURL'메소드를 사용하는 방법
//

만약 위 방법 1의 코드를 사용하면서 iframe을 사용하는 것이 보안 문제로 인해 불가능하다면, 
iOS 9부터는 `canOpenURL` 메소드를 사용하여 URL Scheme이 실행 가능한지 확인할 수 있습니다. 
이를 사용하여 `openAppOrStore()` 함수를 다음과 같이 변경할 수 있습니다.

function openAppOrStore() {
  var appURL = "yourappname://";
  var appStoreURL = "https://itunes.apple.com/app/yourappname/id1234567890";
  
  // 앱이 설치되어 있는지 확인
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
      // 앱이 설치되어 있다면 앱 실행
      window.location.href = appURL;
    }
  };
  xhr.open("GET", appURL, true);
  xhr.send();
  
  // 앱이 설치되어 있지 않다면 앱스토어 다운로드 페이지로 이동
  setTimeout(function() {
    window.location.href = appStoreURL;
  }, 4000);
}
위 코드에서는 XMLHttpRequest를 사용하여 URL Scheme이 실행 가능한지를 확인합니다. 
이 때, `open` 메소드의 `async` 파라미터를 true로 설정하여 비동기 요청을 수행하게 됩니다. 
요청이 완료되면 `readyState`가 4이고, `status`가 200인 경우에는 
앱이 설치되어 있다는 것을 의미하기 때문에 앱을 실행합니다. 
그렇지 않은 경우에는 앱스토어 페이지로 이동합니다.


스마트폰 BTC 채굴앱
https://get.cryptobrowser.site/34473645

 

Earn coins while browsing the web

Earn bitcoins while watching videos, chatting, or playing online. It has never been so easy to increase your income! Tell your friends about CryptoTab Browser, invite them to join, and earn more together. Grow your network—get more profit!

get.cryptobrowser.site


2021.03.16 - [iOS/Tips] - Universal Link (1/4) - 네이티브 환경설정
2021.03.16 - [iOS/Tips] - Universal Link (2/4) - 네이티브 링크 수신
2021.03.16 - [iOS/Tips] - Universal Link (3/4) - 웹서버 환경 설정
2021.03.16 - [iOS/Tips] - Universal Link (4/4) - 웹서버 환경 검증
2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)
2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)
2020/12/10 - [iOS/Tips] - Custom UserAgent 설정
2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거
2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기
2020/12/10 - [개발노트] - Bluetooth UUID
2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법
2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동
2020/08/21 - [Android/Tips] - aab파일 apk파일로 변환
2020/08/11 - [iOS/Swift] - WKWebView 화면 출력 완료 이벤트
2020/08/06 - [iOS/Tips] - 개발관련 폴더 경로
2020/07/19 - [Android/Tips] - 안드로이드 원격 디버깅 방법
2020/07/18 - [Android/Tips] - Cannot convert string value 'JETPACK_COMPOSE' to an enum value of type 'com.android.builder.model.AndroidGradlePluginProjectFlags$BooleanFlag' (valid case insensitive values: APPLICATION_R_CLASS_CONSTANT_IDS, TEST_R_CLASS_CONSTANT_IDS, TRANSITIVE_R_CLASS)
2020/07/18 - [Android/Tips] - OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2020/07/17 - [iOS/Tips] - 웹에서 iOS 앱 설치여부 체크

반응형

'개발 > Note' 카테고리의 다른 글

Bluetooth UUID  (0) 2020.12.10
모바일 앱 메모리덤프 이슈 해결방법  (0) 2020.12.08
SMC(System Management Controller) 재설정  (0) 2020.07.11
NVRAM(PRAM) 재설정 방법  (0) 2020.07.11
duplicate symbol 에러 해결  (0) 2020.06.16
블로그 이미지

SKY STORY

,