December 6, 2021

디바이스마트 미디어:

[66호] 원하는 색상으로 제어가 가능한 아두이노 IoT 스마트 무드등 키트 -

2021-06-25

★2021 ICT 융합 프로젝트 공모전 결과 발표! -

2021-05-12

디바이스마트 국내 온라인 유통사 유일 벨로다인 라이다 공급! -

2021-02-16

★총 상금 500만원 /2021 ICT 융합 프로젝트 공모전★ -

2021-01-18

디바이스마트 온라인 매거진 전자책(PDF)이 무료! -

2020-09-29

[61호]음성으로 제어하는 간접등 만들기 -

2020-08-26

디바이스마트 자체제작 코딩키트 ‘코딩 도담도담’ 출시 -

2020-08-10

GGM AC모터 대량등록! -

2020-07-10

[60호]초소형 레이더 MDR, 어떻게 제어하고 활용하나 -

2020-06-30

[60호]NANO 33 IoT보드를 활용한 블루투스 수평계 만들기 -

2020-06-30

라즈베리파이3가 드디어 출시!!! (Now Raspberry Pi 3 is Coming!!) -

2016-02-29

MoonWalker Actuator 판매개시!! -

2015-08-27

디바이스마트 레이저가공, 밀링, 선반, 라우터 등 커스텀서비스 견적요청 방법 설명동영상 입니다. -

2015-06-09

디바이스마트와 인텔®이 함께하는 IoT 경진대회! -

2015-05-19

드디어 adafruit도 디바이스마트에서 쉽고 저렴하게 !! -

2015-03-25

[29호] Intel Edison Review -

2015-03-10

Pololu 공식 Distributor 디바이스마트, Pololu 상품 판매 개시!! -

2015-03-09

[칩센]블루투스 전 제품 10%가격할인!! -

2015-02-02

[Arduino]Uno(R3) 구입시 37종 센서키트 할인이벤트!! -

2015-02-02

[M.A.I]Ahram_ISP_V1.5 60개 한정수량 할인이벤트!! -

2015-02-02

[67호]메타버스를 이용한 문서 보안 시스템

67 ict_ 최우수상 메타버스 (1)

2021 ICT 융합 프로젝트 공모전 최우수상

메타버스를 이용한 문서 보안 시스템

글 | 광운대학교 최예지, 최혁순

 

1.심사평
칩센 우선 Leap Motion과 unity을 통한 가상현실을 이용하는 것이 실제로는 처음 보고, 매우 흥미로웠습니다. 일반적인 실제 사용의 단계라면 어쩌면 번거로울 수도 있겠으나, 작품의 기획 의도인 강화된 보안이 필요한 경우에는 매우 유용한 기술로 판단됩니다. 다단계의 보안 단계를 만들고, AWS를 이용하여 떨어져 있는 다중의 사용자들 간에 보안 적용된 특정 정보 (작품에서는 문서)의 접근 권한을 만들어주는 것 또한 익숙하지 않은 저에게는 매우 놀라웠습니다. 세부적인 기술 내역에 대하여 저도 검토해봐야겠다는 생각이 드는 작품입니다. 다만 소프트웨어적인 구현만으로 이루어진 점은 개인적으로 조금 아쉽고, 동일한 보안 해제 방식을 통해 특정 목적을 가진 기기를 컨트롤할 수 있는 형태라면 기술의 범위가 충분히 확장될 수 있지 않을까 합니다.

펌테크 날로 중요시되는 컴퓨터 보안에 메타버스 개념을 접목한 독창적이고 색다른 형태의 작품으로 핵심요소인 소프트웨어 개발에 따른 각각의 SDK, 개발툴 등을 작품의 성격에 맞게 효율적으로 구성하였으며 전체적으로 작품의 기획의도, 기술 구현도, 완성도 등에서 우수한 작품이라고 생각됩니다.

위드로봇 Leap motion을 이용한 제스처로 보안을 처리한 아이디어가 돋보이는 작품입니다. 공모전의 성격을 감안하여 LeapMotion을 대치할 수 있는 기술까지 같이 연구가 진행되었다면 더욱 훌륭한 연구가 되었을 것 같습니다.

뉴티씨 매우 독특한 발상으로 잘 만들어진 작품입니다. 스마트폰에만 의존하는 보안 시스템에서 발전하여 Cloud server를 활용하여 보다 높은 수준의 보안 시스템을 구현한 예가 될 수 있습니다. 작품의 모양이나 시스템의 표현 방법이나 사용 방법 등을 대폭 개선하면, 좋은 제품으로 탄생할 수도 있을 것 같습니다. 아파트 현관이나 특정 사무실의 보안 시스템도 그런 식으로 만드는 것도 방법인 것 같습니다. 앞으로 기대가 됩니다.

2. 작품 개요
개인 휴대폰을 이용한 문서 공유, 개인 정보 저장, 신상 정보를 이용한 거래 등의 서비스들이 늘어나고 있다. 등본이나 각종 증명서, 회사 기업 자료 등 중요한 문서 파일을 휴대폰에 저장하기도 하고, 회원가입 정보나 여러 사이트의 비밀번호, 개인 정보를 휴대폰에 저장하기도 하며, 인터넷 뱅킹, 휴대폰 결제와 같은 개인정보를 이용한 서비스들을 휴대폰을 통해 사용한다. 이러한 휴대폰 속 개인정보를 이용한 서비스들과 휴대폰에 저장하는 개인정보, 주요 문서들이 늘어남에 따라 이를 악용한 범죄 또한 늘어나고 있다. 이러한 범죄에 우리가 노출됨에 있어 가장 큰 문제는 오직 핸드폰의 보안에만 의존하고 있다는 점이다. 휴대폰에 저장된 대부분의 주요 문서나 개인 정보가 오직 핸드폰의 보안 또는 어플 자체의 보안에만 의존하고 있다. 우리는 이러한 문제점을 인식하고 더욱 함양된 보안성을 갖춘 문서 보안 시스템을 구축하기 위해 메타버스를 이용해보기로 했다. 메타버스를 이용한 보안 시스템의 취약성은 아직 발견된 것이 없으며, 컴퓨터와 휴대폰 두 개의 디바이스를 이용하여 보안 시스템을 구축하기 때문에 더 높은 보안 장벽을 갖는다는 장점이 있다. 이러한 장점을 가진 메타버스 중 우리는 Leap Motion과 Unity를 이용해 시스템을 구축하기로 했다. Leap Motion은 손의 움직임을 인식하는 장치로 이를 이용하면 오직 손의 움직임만을 이용하여 잠금을 해제하는 보안장치를 만들 수 있기 때문에 잠금을 해제하는 기록을 데이터로 남기기 어려워 보안에 유리하다. 또한 Unity를 이용한 3D 가상현실을 만들어 여기에 Leap Motion을 적용한다면, 보안 장치를 사용하는 사용자가 아닌 이상 보안 장치 해제 방식을 파악하기 어려워 보안에 유리하다. 우리는 이러한 장점을 이용하여 Leap Motion, Unity를 이용한 메타버스 문서 보안 시스템을 제작하기로 했다.

3. 작품 설명
3.1. 주요 동작 및 특징
시스템은 Leap Motion을 이용한 1차 보안과 Unity와 앱을 이용한 2차 보안, 1차 보안과 2차 보안 사이의 서버 통신으로 이루어져 있다.
Leap Motion을 이용해 손의 동작을 감지하고 정해진 동작이 수행되면 웹 서버인 AWS DynamoDB로 동작이 수행됨을 알리는 정보가 넘어간다. 서버 통신을 통해 Leap Motion을 이용한 1차 보안이 해제됨을 감지한 AWS DynamoDB는 이 정보를 핸드폰에 설치된 어플로 넘긴다. 어플에서 정보를 받으면 Unity와 앱을 이용한 2차 보안이 실행되고, 2차 보안에서 정해진 순서대로 번호를 터치하게 되면 문서의 잠금이 해제된다.

Leap Motion을 이용한 1차 보안
Leap Motion에 정해진 동작을 수행하면 그 동작에 해당하는 마법진이 생성되고, 정해진 손짓을 통해 생성된 마법진을 뒤로 보낼 수 있다. 정해진 동작을 순서대로 수행하면 그 동작에 해당하는 4종류의 마법진이 순서대로 생성되고, 이 4종류의 마법진을 정해진 손짓을 통해 순서대로 뒤로 보내 circle에 통과시키면 보안이 해제된다. 이때 4종류의 마법진을 정해진 순서대로 circle에 통과시키지 않으면 보안 잠금이 해제되지 않는다.

67 ict_ 최우수상 메타버스 (2)

[코드 가-1] 위 사진에 해당하는 코드

if ((frame.Hands[1].GrabStrength == 1.0) && (frame.Hands[1].PinchStrength == 1.0)) //왼손 grab 후 pinch
{
count += 1;
if (count > 3)
count = 0;
}
if (count == 0)
{
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 손가락 pinch
{
fstone.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && fstone.state == 1) //윗줄 후 왼손, 오른손 no pinch
{
GameObject realplz = Instantiate(fstobj) as GameObject; // 첫 번째 오브젝트 생성

realplz.transform.position = new Vector3(0, 0.5f,0.5f);
fstone.state = 0;
}
}

그림 가-1과 같이 양 손을 pinch 후 떼어내면 마법진이 생성된다.

67 ict_ 최우수상 메타버스 (3)

 

[코드 가-2] 위 사진에 해당하는 코드 

if ((frame.Hands[1].GrabStrength == 1.0) && (frame.Hands[1].PinchStrength == 1.0)) //왼손 grab 후 pinch{
count += 1;
if (count > 3)
count = 0;
}
if (count == 0){
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 손가락 pinch{
fstone.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && fstone.state == 1) //윗줄 후 왼손, 오른손 no pinch{
GameObject realplz = Instantiate(fstobj) as GameObject; // 첫 번째 오브젝트 생성
realplz.transform.position = new Vector3(0, 0.5f,0.5f);
fstone.state = 0;
}
}
else if (count == 1){
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 pinch{
second.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && second.state == 1) //윗 줄 후 왼손, 오른손 no pinch{
GameObject realplz = Instantiate(scdobj) as GameObject; //두 번째 오브젝트 생성
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);
second.state = 0;
}
}
else if (count == 2)
{
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 pinch{
third.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && third.state == 1) //윗 줄 후 왼손, 오른손 no pinch{
GameObject realplz = Instantiate(thdobj) as GameObject; //세 번째 오브젝트 생성
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);
third.state = 0;
}
else if (count == 3)
{
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 pinch{
fourth.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && fourth.state == 1) //윗 줄 후 왼손, 오른손 no pinch{
GameObject realplz = Instantiate(fthobj) as GameObject; //네 번째 오브젝트 생성
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);
fourth.state = 0;
}
}

왼손 grab 후 오른손 pinch 한 번 할 때마다 object, 즉 마법진이 변경된다.

67 ict_ 최우수상 메타버스 (4)

[코드 가-3] 위 사진에 해당하는 코드

if (HandPalmYam > -2f && HandPalmYam < 3.5f && (frame.Hands[1].GrabStrength==1.0 )) //왼손 grab 후 오른손 흔듦{
Debug.Log(“앞”);
this.transform.Translate(0, 2 * Time.deltaTime,0); //오브젝트 앞으로 이동
}
if ((frame.Hands[1].GrabStrength == 1.0) && (frame.Hands[0].GrabStrength == 1.0)) //양손 grab
Destroy(gameObject); //오브젝트 사라짐

 

왼손 grab 후 오른손 흔들면 object, 즉 마법진이 앞으로 이동하다가 circle에 닿으면 사라지게 된다. 이때, 마법진 4종류가 정해진 순서대로 circle에 닿아야만 잠금이 해제된다.

67 ict_ 최우수상 메타버스 (5)

Object, 즉 마법진은 계속해서 회전하고 있다.

67 ict_ 최우수상 메타버스 (7)

코드 가-5에 의해 object, 즉 마법진이 circle에 닿으면 사라지게 된다. 또한 4종류의 마법진이 정해진 순서대로 circle에 닿아야만 보안이 해제된다.

67 ict_ 최우수상 메타버스 (8)

1차 보안과 2차 보안 사이의 서버 통신

67 ict_ 최우수상 메타버스 (9)

67 ict_ 최우수상 메타버스 (10)

Leap Motion을 이용한 1차 보안이 해제됨을 알리는 정보가 AWS DynamoDB로 넘어간다. AWS DynamoDB는 받은 정보를 다시 2차 보안에 사용되는 앱에 넘기고, 앱은 정보를 받으면 보안 해제 시스템이 작동된다. 2차 보안 앱은 1차 보안이 해제되기 전까지는 실행되지 않고, 로딩창에 머무르게 된다. 1차 보안이 해제되었다는 정보를 넘겨받아야 실행이 되는 구조이다.
[그림 나-2]는 DynamoDB에서 leapmotion의 데이터가 초기설정 값인 0000이었지만, 1차 보안을 해제한 후 1234로 바뀐 모습이다.
private void Start() //AWS에서 계정에 대한 인증과 권한을 부여받는 코드이다.

{
UnityInitializer.AttachToGameObject(this.gameObject);
credentials = new CognitoAWSCredentials(“ap-northeast-2:ceafc145-14a2-4c03-b397-22368bc8ab4f”, RegionEndpoint.APNortheast2);
DBclient = new AmazonDynamoDBClient(credentials, RegionEndpoint.APNortheast2);
context = new DynamoDBContext(DBclient);
}

[DynamoDBTable("character_info")] public class Character
{
[DynamoDBHashKey] // Hash key.
public string id { get; set; }
[DynamoDBProperty] public int item { get; set; }
}

public void FindItem() //DB에서 캐릭터 정보 받기
{
context.LoadAsync<Character>(“leapmotion”, (AmazonDynamoDBResult<Character> result) =>
{
// id가 leapmotion인 캐릭터 정보를 DB에서 받아옴
if (result.Exception != null)
{
Debug.LogException(result.Exception);
// 정보를 받아오지 못했을 때의 예외처리

return;
}
c = result.Result;
Debug.Log(c.item); //찾은 캐릭터 정보 중 아이템 정보 출력
}, null);
}

void Update()
{

FindItem();
if (c!=null) //앱 실행 후 초기화되는 aws에서 정보를 받아오는 변수이므로 받아온 정보가 null값인지를 먼저 확인한다.
{
if (c.item == 1234)
{
GameObject.Destroy(this.gameObject);
SceneManager.LoadScene(“realA”);
}
}

사용자가 4번에 걸쳐서 원을 서클에 통과시키면, 4개의 원이 지정된 패턴과 일치하는지를 판별 후, 맞다면 AWS에 접속하여 DynamoDB의 leapmotion이라는 데이터의 값을 1234로 변경해준다.

Unity와 앱을 이용한 2차 보안
AWS DynamoDB로 전달된 1차 보안이 해제됨을 알리는 정보는 만들어둔 핸드폰에 전달된다. 정보를 받은 핸드폰은 앱을 실행시킨다. 실행된 앱에서 정해진 물체에 카메라를 가져가면 키패드가 생성되고, 생성된 키패드에 비밀번호를 순서대로 입력하면 2차 보안이 해제되어 문서를 열람할 수 있게 된다.

67 ict_ 최우수상 메타버스 (11)

AR 키패드 화면으로 넘어왔지만, 지정된 물체를 비추지 않아, 키패드가 나타나지 않는 모습이다.

67 ict_ 최우수상 메타버스 (12)
지정된 물체를 비추고 나서, 키패드가 나타나는 모습이다.

if (count == 4) //사용자가 키패드를 누른 횟수를 센다
{
Debug.Log(“full”);
for (int i = 0; i < 4; i++)
{
if (answer[i] != realanswer[i]) //입력 비밀번호랑 정답 비밀번호랑 비교
{
SceneManager.LoadScene(“retry”);
break;
}

기본적으로 앱은 AWS와 계속해서 통신을 하고 DynamoDB의 leapmotion 데이터의 값을 반복해서 불러들이는 작업을 하고, 받아온 값이 최초 설정값인 0000이 아닌 1234일 때, 씬을 변경하여 앱을 실행시키는 역할을 한다.

67 ict_ 최우수상 메타버스 (13)

3.2. 전체 시스템 구성
위 시스템은 Leap Motion을 이용한 1차 보안과 Unity와 앱을 이용한 2차 보안, 1차 보안과 2차 보안 사이의 서버 통신으로 이루어져 있다.
Leap Motion을 이용해 손의 동작을 감지하고 정해진 동작이 수행되면 웹 서버인 AWS DynamoDB로 동작이 수행됨을 알리는 정보가 넘어간다. 서버 통신을 통해 Leap Motion을 이용한 1차 보안이 해제됨을 감지한 AWS DynamoDB는 이 정보를 핸드폰에 설치된 어플로 넘긴다. 어플에서 정보를 받으면 Unity와 앱을 이용한 2차 보안이 실행되고, 2차 보안 앱에서 지정된 물체를 비추게 되면 키패드가 나타나고, 키패드에 비밀번호를 입력하게 되면 2차 보안이 해제되면서 문서의 잠금이 해제된다. 따라서 키패드를 거치기 전, 지정된 물체를 알고 있어야 하고, 그것을 비추어야만 비밀번호를 입력할 수 있다는 점에서 2차 보안 속에 한 단계의 보조 보안단계가 더 있다고 볼 수 있다.

3.3. 개발 환경
위 시스템은 Leap Motion을 이용한 1차 보안과 Unity와 앱을 이용한 2차 보안, 1차 보안과 2차 보안 사이의 서버 통신으로 이루어져 있다. 먼저 Leap Motion을 이용한 1차 보안에서 Leap Motion과 Unity를 이용하며, 이를 위해 Leap Motion SDK와 개발 Tool로 Unity 2D, Unity 3D를 사용하였다. 또한 Unity 개발 언어로 C#을 이용하였으며 3D 가상 현실 환경을 구축하기 위해 Asset store를 사용하였다. 또한 개발 언어를 위한 Tool로 Visual Studio를 사용하였다. 다음으로 1차 보안과 2차 보안 사이의 서버 통신을 위한 시스템으로 AWS와 DynamoDB를 사용하였다. 마지막으로 App과 Unity를 이용한 2차 보안에서 App 개발과 보안 환경 구축을 위해 개발 Tool로 Unity 2D, Unity 3D를 사용하였다. 또한 Unity 개발 언어로 C#을 이용하였으며 3D 가상 현실 환경을 구축하기 위해 Asset store와 Vuforia를 사용하였다. 또한 개발 언어를 위한 Tool로 Visual Studio를 사용하였다.

Leap Motion을 이용한 1차 보안
생체 움직임 감지를 위해 Leap Motion을 사용하였으며, Leap Motion을 사용하기 위해 Leap Motion SDK를 사용하였다. Leap Motion 이용을 위한 증강 현실을 구현하기 위한 개발 Tool로 Unity 2D와 Unity 3D를 사용하였으며, Unity 개발 언어로 C#을 사용하고, 개발 언어를 사용하기 위한 Tool로 Visual Studio를 사용하였다. 3D 증강 현실 구현을 위해 Asset Store를 사용하였으며, AR엔진으로 Vuforia를 이용하였다.

1차 보안과 2차 보안 사이의 서버 통신
1차 보안에서의 정보를 서버로 옮기고, 서버에 저장된 정보를 다시 휴대폰 앱으로 전송하기 위한 웹 서버를 구축하였다. 이때 AWS를 사용하여 웹서버를 구축하였다. 웹 서버로 통신한 정보를 저장하기 위해 DynamoDB를 데이터베이스로 사용하였다.

Unity와 App을 이용한 2차 보안
증강 현실을 이용한 App 개발을 위한 개발 Tool로 Unity 2D와 Unity 3D를 사용하였으며, Unity 개발 언어로 C#을 사용하고, IDE로 Visual Studio를 사용하였다. 3D 증강 현실 구현을 위해 Asset Store를 사용하였으며, AR엔진으로 Vuforia를 이용하였다.

4. 단계별 제작 과정
시스템은 ‘Leap Motion을 이용한 1차 보안’과 ‘Unity와 앱을 이용한 2차 보안’, ‘1차 보안과 2차 보안 사이의 서버 통신’으로 단계를 나누어 제작하였다.

4.1. Leap Motion을 이용한 1차 보안
이 단계에서는 먼저 Leap Motion을 Unity와 연동시킨 뒤 Leap Motion의 동작 인식 감도를 확인하였다. 이후 Unity를 이용해 Leap Motion을 이용하기 위한 3D 가상 현실과 보안 시스템을 구축하였고, 가상 현실과 보안 시스템을 제어하기 위한 코드를 작성하였다.

67 ict_ 최우수상 메타버스 (1)

그림 4-1-1과 같이 Leap Motion을 이용하기에 앞서 Leap Motion을 Unity에 연동시키고, Unity에서의 Leap Motion 작동 여부와 실제 작동 환경을 테스트하였다. 이후 Leap Motion의 손동작 인식 감도를 확인하였다.

67 ict_ 최우수상 메타버스 (14)
다음으로 그림 4-4-2와 같이 Leap Motion이 사용되는 가상 현실을 Unity를 통해 구축하였다. 배경과 바닥을 3D object와 asset을 이용하여 구현했으며, 손동작에 따라 생성되고 작동될 3D object를 만들었다. 마지막으로 코드 3-1-가-1,2,3,4,5와 같이 Leap Motion에 감지된 동작에 따라 실행될 기능에 대해 코드를 작성하였다. 왼손 grab 후에 pinch 한 번 할 때마다 object가 바뀌고, 양손을 pinch 후에 떼면 object가 생성되는 코드, 왼손 grab 후 오른손을 흔들면 object가 앞으로 이동하는 코드, 양손 grab시에 object가 사라지는 코드, object가 회전하는 코드, object가 circle에 닿으면 사라지는 코드, object가 정해진 순서대로 circle에 닿으면 그 정보를 관리자 object에 전달하는 코드를 작성하였다.

4.2. 1차 보안과 2차 보안 사이의 서버 통신
이 단계에서는 먼저 1차 보안을 담당하는 노트북과 2차 보안을 담당하는 핸드폰 App사이의 서버 통신을 위한 웹서버를 구축하였다. 이후 노트북의 정보가 구축한 웹서버로 전달되는지 여부를 확인하였다. 다음으로 웹서버에 저장된 데이터 베이스가 휴대폰 App으로 전달되는지 여부를 확인하였다. 마지막으로 1차 보안이 해제됨을 알리는 정보를 웹 서버에 전달하고 웹 서버는 이를 데이터 베이스에 저장하여 2차 보안을 담당하는 휴대폰 App으로 전달하는 코드를 작성하였다.

67 ict_ 최우수상 메타버스 (15)

그림 4-2-1과 같이 웹서버를 구축하였다. DynamoDB에 leapmotion 데이터가 저장되어 있는 모습을 볼 수 있다.

 

67 ict_ 최우수상 메타버스 (16)

그림 4-2-2와 같이 1차 보안과 웹 서버 사이의 서버 통신이 원활하게 이루어지는지 확인하였다.

67 ict_ 최우수상 메타버스 (17)

그림 4-2-3과 같이 웹 서버에 저장된 데이터 베이스가 2차 보안을 담당하는 휴대폰 App으로 잘 전달되는지 여부를 확인하였다. DynamoDB의 데이터 leapmotion의 정보를 잘 받았는지 확인하는 콘솔로그 창이다.
코드 4-2-1과 같이 1차 보안이 해제됨을 알리는 정보를 웹 서버에 전달하고 웹 서버는 이를 데이터 베이스에 저장하여 2차 보안을 담당하는 휴대폰 App으로 전달하는 코드를 작성하였다.

4.3. Unity와 App을 이용한 2차 보안
이 단계에서는 노트북에서 Unity를 이용하여 2차 보안의 가상 현실을 만든 뒤, 순서대로 정해진 비밀번호를 입력하면 문서 보안이 해제되는 코드를 작성하였다. 이후 제작한 App을 휴대폰에 복제하였다. 마지막으로 제작한 App이 구축한 웹 서버를 통해 1차 보안이 해제됨을 알리는 데이터 베이스를 전달하면 App이 실행되도록 하는 코드를 작성하였다.

67 ict_ 최우수상 메타버스 (18)

그림 4-3-1과 같이 Unity를 이용하여 2차 보안에 사용할 가상 현실을 제작했다.
그림 4-3-2와 같이 앞서 노트북으로 만든 App을 휴대폰에 빌드하여 휴대폰으로 App이용이 가능하게 만들었다.

67 ict_ 최우수상 메타버스 (19)

 5. 사용한 제품 리스트

‘Leap Motion을 이용한 1차 보안’과 ‘Unity와 앱을 이용한 2차 보안’, ‘1차 보안과 2차 보안 사이의 서버 통신’으로 나누어져 있다. 이 중 Leap Motion을 이용한 1차 보안 단계에서 Leap Motion Controller제품을 사용하였다.

6. 회로도
작품의 전체 회로도는 그림 6-1과 같다. Leap Motion과 노트북이 1차 보안을 위해 연결되어 있으며, 2차 보안인 휴대폰 App과 웹 서버를 통해 연결되어 있다.

67 ict_ 최우수상 메타버스 (20)

7. 소스코드
7.1. Leap Motion을 이용한 1차 보안 코드
Leap Motion Hand model 코드

void Update(){
controller = new Controller();
Frame frame = controller.Frame();
List<Hand> hands = frame.Hands;
Frame previous = controller.Frame(1);
Hand previous_leapHand = previous.Hands[0];
Vector handOrigin = frame.Hands[0].PalmPosition;
Vector previoushandOrigin = previous_leapHand.PalmPosition;
if ((frame.Hands[1].GrabStrength == 1.0) && (frame.Hands[1].PinchStrength == 1.0)){
count += 1;
if (count > 3)
count = 0;
}
if (count == 0) {
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0)
{
fstone.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && fstone.state == 1) {
GameObject realplz = Instantiate(fstobj) as GameObject;

realplz.transform.position = new Vector3(0, 0.5f,0.5f);
fstone.state = 0;
}
}
else if (count == 1){
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0){
second.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && second.state == 1){
GameObject realplz = Instantiate(scdobj) as GameObject;

realplz.transform.position = new Vector3(0, 0.5f, 0.5f);
second.state = 0;
}
}
else if (count == 2) {
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0){
third.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && third.state == 1){
GameObject realplz = Instantiate(thdobj) as GameObject;
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);
third.state = 0;
}
else if (count == 3){
if (frame.Hands[0].PinchStrength == 1.0 && frame.Hands[1].PinchStrength == 1.0){
fourth.state = 1;
}
if (frame.Hands[0].PinchStrength < 1.0 && frame.Hands[1].PinchStrength < 1.0 && fourth.state == 1){
GameObject realplz = Instantiate(fthobj) as GameObject;
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);
fourth.state = 0;
}
}
strength1 = frame.Hands[0].GrabStrength;
strength2 = frame.Hands[1].GrabStrength;
Debug.Log(“왼손??” + strength2);
Debug.Log(“오른손??” + strength1);
}
}

Leap Motion New Behavior 코드

Controller controller;
float HandPalmPitch;
float HandPalmRoll;
float HandPalmYam;
float HandWristRot;
Rigidbody rb;
void Start(){
}
void Update(){
controller = new Controller();
Frame frame = controller.Frame();
List<Hand> hands = frame.Hands;
if (frame.Hands.Count > 0){
Hand fristHand = hands[0];
}
HandPalmPitch = hands[0].PalmNormal.Pitch;
HandPalmRoll = hands[0].PalmNormal.Roll;
HandPalmYam = hands[0].PalmNormal.Yaw;
HandWristRot = hands[0].WristPosition.Pitch;
Debug.Log(“Pitch : ” + HandPalmPitch);
Debug.Log(“Roll : ” + HandPalmRoll);
Debug.Log(“Yam : ” + HandPalmYam);
if (HandPalmYam > -2f && HandPalmYam < 3.5f && (frame.Hands[1].GrabStrength==1.0 )){
Debug.Log(“앞”);
this.transform.Translate(0, 2 * Time.deltaTime,0);
}
this.transform.Rotate(0, 30, 0);
if ((frame.Hands[1].GrabStrength == 1.0) && (frame.Hands[0].GrabStrength == 1.0))
Destroy(gameObject);
}
}

Leap Motion 관리자 object 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class c1direc : MonoBehaviour{
GameObject director;
void Start(){
director = GameObject.Find(“director”);
}
void Update(){
if (this.transform.position.z > 3){
director.GetComponent<director>().arr[director.GetComponent<director>().ind] = 0;
director.GetComponent<director>().ind += 1;
}
}
}

7.2. 1차 보안과 2차 보안 사이의 서버 통신 코드
Leap Motion 서버 통신 director 코드

public class director : MonoBehaviour
{
int count;
public int [] arr = { -1, -1, -1, -1 };
int[] arranswer = { 0, 1, 2, 3 };
DynamoDBContext context;
AmazonDynamoDBClient DBclient;
CognitoAWSCredentials credentials;
Character c;
public Camera a;
private void Start()
{
UnityInitializer.AttachToGameObject(this.gameObject);
credentials = new CognitoAWSCredentials(“ap-northeast-2:ceafc145-14a2-4c03-b397-22368bc8ab4f”, RegionEndpoint.APNortheast2);
DBclient = new AmazonDynamoDBClient(credentials, RegionEndpoint.APNortheast2);
context = new DynamoDBContext(DBclient);
}
[DynamoDBTable("character_info")] public class Character
{
[DynamoDBHashKey] // Hash key.
public string id { get; set; }
[DynamoDBProperty] public int item { get; set; }
}
private void CreateCharacter() //캐릭터 정보를 DB에 올리기
{
Character c1 = new Character
{
id = “leapmotion”,
item = 1234,
};
context.SaveAsync(c1, (result) =>
{
if (result.Exception == null)
Debug.Log(“Success!”);
else
Debug.Log(result.Exception);
});
}
void Update() //써클을 통과한 원이 지정된 패턴과 일치하는지 확인 후, 일치하면 서버에 정보를 보냄
{

for(int i = 0; i <= 3; i++)
{
if (arr[i] == arranswer[i])
{
count += 1;
}
else if (arr[i] != arranswer[i])
break;
}
if (count== 4)
{
CreateCharacter();
Debug.Log(“카운트!!!!!!!!!!!!!!!!!111″);
}

7.3. Unity와 App을 이용한 2차 보안 코드
서버와 통신을 하는 direc코드

private void Start() //AWS에 접속해서 인증받고 권한을 받아오는 단계
{
UnityInitializer.AttachToGameObject(this.gameObject);
credentials = new CognitoAWSCredentials(“ap-northeast-2:ceafc145-14a2-4c03-b397-22368bc8ab4f”, RegionEndpoint.APNortheast2);
DBclient = new AmazonDynamoDBClient(credentials, RegionEndpoint.APNortheast2);
context = new DynamoDBContext(DBclient);

}

[DynamoDBTable("character_info")] public class Character
{
[DynamoDBHashKey] // Hash key.
public string id { get; set; }
[DynamoDBProperty] public int item { get; set; }
}
public void FindItem() //DB에서 캐릭터 정보 받기
{
context.LoadAsync<Character>(“leapmotion”, (AmazonDynamoDBResult<Character> result) =>
{
// id가 leapmotion인 캐릭터 정보를 DB에서 받아옴
if (result.Exception != null)
{
Debug.LogException(result.Exception);
return;
}
c = result.Result;
Debug.Log(c.item); //찾은 캐릭터 정보 중 아이템 정보 출력
}, null);
}
void Update()
{

FindItem();
if (c!=null) //앱 실행 후 초기화되는 aws에서 정보를 받아오는 변수이므로 받아온 정보가 null값인지를 먼저 확인한다.
{
if (c.item == 1234)
{

GameObject.Destroy(this.gameObject);
SceneManager.LoadScene(“realA”);
} }}

입력한 비밀번호를 확인하는 director 코드

public class director : MonoBehaviour
{
public int[] answer = new int[4] { -1, -1, -1, -1 }; //입력받을 비밀번호를 저장할 배열
int[] realanswer = new int[4] { 2, 1, 3, 0 }; //원래 비밀번호 정답
public int count = 0;
int point = 0;
void Start()
{
a.enabled = true;
iinteraction = GameObject.Find(“iinteraction”);
interaction1 = GameObject.Find(“interaction1″);
interaction2 = GameObject.Find(“interaction2″);
interation3 = GameObject.Find(“interation3″);
}
// Update is called once per frame
void Update()
{
Debug.Log(count);
if (count == 4) //네개의 비밀번호를 입력받으면 일치하는 비밀번호인지 확인하는 코드
{
Debug.Log(“full”);
for (int i = 0; i < 4; i++)
{
if (answer[i] != realanswer[i])
{
SceneManager.LoadScene(“retry”);
break;
}
}
}
if (point ==4)
SceneManager.LoadScene(“EndScene”);
}

어떤 키패드가 눌렸는지 확인하는 interaction1 코드

void Start()
{ director = GameObject.Find(“director”);
mat = GetComponent<Renderer>().material;
mat.SetFloat(“_Mode”, 2);
mat.SetInt(“_SrcBlend”, (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
mat.SetInt(“_DstBlend”, (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
mat.SetInt(“_ZWrite”, 0);
mat.DisableKeyword(“_ALPHATEST_ON”);
mat.EnableKeyword(“_ALPHABLEND_ON”);
mat.DisableKeyword(“_ALPHAPREMULTIPLY_ON”);
mat.renderQueue = 3000;
defaultColor = new Color32(255, 255, 255, 255);
selectedColor = new Color32(255, 0, 0, 255);

mat.color = defaultColor;
}
void Update()
{
if (die == 1)
{
Destroy(gameObject);
}
}
void touchBegan() //키패드의 어떤 숫자가 눌렸는지 확인하는 코드
{
director.GetComponent<director>().count+=1;
director.GetComponent<director>().answer[director.GetComponent<director>().count-1] = 1;

8. 참고 문헌
[1] https://bit.ly/3wcnOow
[2] https://bit.ly/2QNPyjk
[3] https://bit.ly/31u0aWz
[4] https://amzn.to/39rTzQU
[5] https://bit.ly/3wfrber
[6] https://amzn.to/3dneDJx
[7] https://bit.ly/31y7Abi

 

 

 

Leave A Comment

*